Skip to content

Commit

Permalink
add checkbox flag & mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
softmarshmallow committed Mar 29, 2022
1 parent 9eec1cc commit a0dd9fd
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 4 deletions.
2 changes: 1 addition & 1 deletion externals/reflect-core
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import type { ElementCssStyleData } from "@coli.codes/css";
import type {
BorderSide,
Color,
ICheckboxManifest,
IWHStyleWidget,
MouseCursor,
} from "@reflect-ui/core";
import { WidgetKey } from "../../widget-key";
import type { StylableJSXElementConfig } from "../../widget-core";
import { Container } from "../container";
import * as css from "@web-builder/styles";
import { JSX, JSXAttribute, StringLiteral } from "coli";

/**
* A jsx attibute to indicate input type as checkbox
*/
const attr_type_range = new JSXAttribute("type", new StringLiteral("checkbox"));

/**
* checkbox
*
*
* @see
* - [html#progress](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
*/
export class HtmlInputCheckbox extends Container implements ICheckboxManifest {
_type = "input/checkbox";

value?: boolean;

/**
* @deprecated - not supported natively
*/
tristate?: boolean;
mouseCursor?: MouseCursor;
activeColor?: Color;
// fillColor?: ReflectStateProperty<Color>;
checkColor?: Color;
focusColor?: Color;

/**
* @deprecated - not supported natively
*/
hoverColor?: Color;
// overlayColor?: ReflectStateProperty<Color>;

/**
* @deprecated - not supported natively
*/
splashRadius?: number;
// visualDensity?: VisualDensity,
autofocus?: boolean;
// shape?: OutlinedBorder;

/**
* @deprecated - not supported natively
*/
side?: BorderSide;

constructor({
key,

value,
tristate,
mouseCursor,
activeColor,
checkColor,
focusColor,
hoverColor,
splashRadius,
autofocus,
side,

...rest
}: {
key: WidgetKey;
} & IWHStyleWidget &
ICheckboxManifest) {
super({ key, ...rest });

this.value = value;
this.tristate = tristate;
this.mouseCursor = mouseCursor;
this.activeColor = activeColor;
this.checkColor = checkColor;
this.focusColor = focusColor;
this.hoverColor = hoverColor;
this.splashRadius = splashRadius;
this.autofocus = autofocus;
this.side = side;
}

get indeterminate() {
return this.value === undefined;
}

styleData(): ElementCssStyleData {
const containerstyle = super.styleData();

return {
// general layouts, continer ---------------------
...containerstyle,
// -------------------------------------------------

"border-radius": undefined, // clear to use default appearance
"background-color": undefined, // clear to use default appearance
padding: undefined,

// general slider styles
"accent-color": css.color(this.activeColor),
};
}

jsxConfig(): StylableJSXElementConfig {
const attrs = [
attr_type_range,
this.indeterminate
? new JSXAttribute("indeterminate")
: new JSXAttribute(
"value",
new StringLiteral(this.value ? "checked" : "unchecked")
),
].filter(Boolean);

return <StylableJSXElementConfig>{
type: "tag-and-attr",
tag: JSX.identifier("input"),
attributes: attrs,
};
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { HtmlTextField as TextInput } from "./html-input-text";
export { HtmlSlider as Slider } from "./html-input-range";
export { HtmlInputCheckbox as Checkbox } from "./html-input-checkbox";
2 changes: 2 additions & 0 deletions packages/designto-token/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ function handleNode(
if (config.disable_detection) {
// skip detection
} else {
// TODO: only execute detection if all the nested children is not flagged as other component.

// - icon -
const _detect_if_icon = detectIf.icon(node);
if (_detect_if_icon.result) {
Expand Down
5 changes: 5 additions & 0 deletions packages/designto-token/support-flags/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { tokenize_flagged_progress } from "./token-progress";
import { tokenize_flagged_google_maps_view } from "./token-x-google-maps-view";
import { tokenize_flagged_youtube_view } from "./token-x-youtube-view";
import { tokenize_flagged_camera_view } from "./token-x-camera-display";
import { tokenize_flagged_checkbox } from "./token-checkbox";

export default function handleWithFlags(node: ReflectSceneNode) {
const flags = parse(node.name);
Expand Down Expand Up @@ -54,6 +55,10 @@ function _handle_with_flags(node, flags: FlagsParseResult) {
return tokenize_flagged_button(node, flags[keys.flag_key__as_button]);
}

if (flags.__meta?.contains_checkbox_flag) {
return tokenize_flagged_checkbox(node, flags[keys.flag_key__as_checkbox]);
}

if (flags.__meta?.contains_input_flag) {
return tokenize_flagged_textfield(node, flags[keys.flag_key__as_input]);
}
Expand Down
86 changes: 86 additions & 0 deletions packages/designto-token/support-flags/token-checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Checkbox, Container, ICheckboxManifest } from "@reflect-ui/core";
import type { AsCheckboxFlag } from "@code-features/flags";
import type {
ReflectFrameNode,
ReflectSceneNode,
} from "@design-sdk/figma-node";
import { WrappingContainer } from "../../tokens";
import assert from "assert";
import { unwrappedChild } from "../../wrappings";
import { tokenizeLayout } from "../../token-layout";
import { keyFromNode } from "../../key";

export function tokenize_flagged_checkbox(
node: ReflectSceneNode,
flag: AsCheckboxFlag
): Checkbox | WrappingContainer<Checkbox> {
if (flag.value === false) return;

const validated = validate_checkbox(node);
if (validated.error === false) {
switch (validated.__type) {
case "frame-as-checkbox": {
const { checkbox_base, checkbox_value } = validated;

const _key = keyFromNode(node);

const container = unwrappedChild(
tokenizeLayout.fromFrame(
checkbox_base,
checkbox_base.children,
{ is_root: false },
{}
)
) as Container;

const checked = checkbox_value && checkbox_value.visible;

return new WrappingContainer({
...container,
key: keyFromNode(node),
child: new Checkbox({
key: _key,
fillColor: { default: checkbox_base?.primaryColor },
checkColor: checkbox_value?.primaryColor,
value: checked,
}),
});
}
default:
throw new Error("unreachable");
}
} else {
throw new Error(validated.error);
}
}

/**
* validate if layer casted as checkbox can be actually tokenized to checkbox.
* @param node
*/
function validate_checkbox(node: ReflectSceneNode):
| {
__type: "frame-as-checkbox";
error: false;
checkbox_base: ReflectFrameNode;
checkbox_value?: ReflectSceneNode;
}
| { error: string } {
assert(!!node, "target must not be null or undefined");
switch (node.type) {
case "FRAME": {
const firstvaluenode = node.children.find(
(child) => child.type === "VECTOR"
);

return {
__type: "frame-as-checkbox",
checkbox_base: node,
checkbox_value: firstvaluenode,
error: false,
};
}
default:
return { error: "checkbox target is not a valid frame node" };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as web from "@web-builder/core";
import * as core from "@reflect-ui/core";

export function compose_unwrapped_checkbox(
key,
widget: core.Checkbox,
container?: core.Container
): web.Checkbox {
return new web.Checkbox({ ...(container ?? {}), ...widget, key });
}
11 changes: 11 additions & 0 deletions packages/designto-web/tokens-to-web-widget/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { compose_wrapped_with_overflow_box } from "./compose-wrapped-with-overfl
import { compose_wrapped_with_expanded } from "./compose-wrapped-with-expanded";
import { compose_unwrapped_text_input } from "./compose-unwrapped-text-field";
import { compose_unwrapped_button } from "./compose-unwrapped-button";
import { compose_unwrapped_checkbox } from "./compose-unwrapped-checkbox";
import { compose_unwrapped_slider } from "./compose-unwrapped-slider";
import { compose_unwrapped_progress } from "./compose-unwrapped-progress";
import { compose_instanciation } from "./compose-instanciation";
Expand Down Expand Up @@ -242,6 +243,10 @@ function compose<T extends JsxWidget>(
// TODO: widget.icon - not supported
thisWebWidget = compose_unwrapped_button(_key, widget);
}
// checkbox
else if (widget instanceof core.Checkbox) {
thisWebWidget = compose_unwrapped_checkbox(_key, widget);
}
// textfield
else if (widget instanceof core.TextField) {
thisWebWidget = compose_unwrapped_text_input(_key, widget);
Expand All @@ -263,6 +268,8 @@ function compose<T extends JsxWidget>(
thisWebWidget = compose_unwrapped_text_input(_key, widget.child, widget);
} else if (widget.child instanceof core.ButtonStyleButton) {
thisWebWidget = compose_unwrapped_button(_key, widget.child, widget);
} else if (widget.child instanceof core.Checkbox) {
thisWebWidget = compose_unwrapped_checkbox(_key, widget.child, widget);
} else if (widget.child instanceof core.Slider) {
thisWebWidget = compose_unwrapped_slider(_key, widget.child, widget);
} else if (widget.child instanceof core.ProgressIndicator) {
Expand All @@ -283,6 +290,10 @@ function compose<T extends JsxWidget>(
// --- --- --- --- ---
// #endregion
else {
console.error(
`Unsupported web widget type: ${widget.child.constructor.name}`,
widget.child
);
throw new Error(
`Unsupported web widget type: ${widget.child.constructor.name}`
);
Expand Down
11 changes: 11 additions & 0 deletions packages/support-flags/--as-checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// primary
export const flag_key__as_checkbox = "as-checkbox";

export const flag_key_alias__as_checkbox = [flag_key__as_checkbox];

export interface AsCheckboxFlag {
flag: typeof flag_key__as_checkbox;

value: boolean;
_raw?: string;
}
7 changes: 4 additions & 3 deletions packages/support-flags/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { flag_key_alias__as_p, flag_key__as_p } from "./--as-p";
import { flag_key_alias__as_span, flag_key__as_span } from "./--as-span";

import { flag_key__as_button, flag_key_alias__as_button } from "./--as-button";
// prettier-ignore
import { flag_key__as_checkbox, flag_key_alias__as_checkbox } from "./--as-checkbox";
import { flag_key__as_input, flag_key_alias_as_input } from "./--as-input";
import { flag_key__as_slider, flag_key_alias__as_slider } from "./--as-slider";
// prettier-ignore
Expand Down Expand Up @@ -61,11 +63,9 @@ export { flag_key__as_p };
export { flag_key__as_span };

export { flag_key__as_button };

export { flag_key__as_checkbox };
export { flag_key__as_input };

export { flag_key__as_slider };

export { flag_key__as_progress };

export {
Expand Down Expand Up @@ -101,6 +101,7 @@ export const alias = {
as_p: flag_key_alias__as_p,
as_span: flag_key_alias__as_span,
as_button: flag_key_alias__as_button,
as_checkbox: flag_key_alias__as_checkbox,
as_input: flag_key_alias_as_input,
as_slider: flag_key_alias__as_slider,
as_progress: flag_key_alias__as_progress,
Expand Down
Loading

1 comment on commit a0dd9fd

@vercel
Copy link

@vercel vercel bot commented on a0dd9fd Mar 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.