|
1 | | -import { JSXElementConfig, WidgetKey } from "@web-builder/core"; |
2 | | -import { JSX, JSXAttribute, Snippet } from "coli"; |
3 | | -import { ReactWidget } from ".."; |
| 1 | +import type { CSSProperties, ElementCssStyleData } from "@coli.codes/css"; |
| 2 | +import type { JSXElementConfig, StylableJsxWidget } from "@web-builder/core"; |
| 3 | +import type { |
| 4 | + IButtonStyleButton, |
| 5 | + IButtonStyleButtonProps, |
| 6 | + ITextStyle, |
| 7 | + ButtonStyle, |
| 8 | + IWHStyleWidget, |
| 9 | + Widget, |
| 10 | +} from "@reflect-ui/core"; |
| 11 | +import { Text } from "@reflect-ui/core"; |
| 12 | +import { Container } from ".."; |
| 13 | +import { WidgetKey } from "../../widget-key"; |
| 14 | +import { JSX } from "coli"; |
| 15 | +import * as css from "@web-builder/styles"; |
4 | 16 |
|
5 | | -export class Button extends ReactWidget { |
6 | | - constructor({ key }: { key: WidgetKey }) { |
7 | | - super({ key }); |
8 | | - } |
| 17 | +/** |
| 18 | + * Html5 Button Will have built in support for... |
| 19 | + * |
| 20 | + * |
| 21 | + * - onClick callback |
| 22 | + * - hover styles |
| 23 | + * - focus styles |
| 24 | + * - disabled styles |
| 25 | + * - active styles |
| 26 | + * |
| 27 | + * |
| 28 | + * Learn more at |
| 29 | + * - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) |
| 30 | + * - [html spec](https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element) |
| 31 | + * |
| 32 | + */ |
| 33 | +export class HtmlButton extends Container implements IButtonStyleButton { |
| 34 | + _type = "button"; |
| 35 | + |
| 36 | + /** |
| 37 | + * The name of the button, submitted as a pair with the button’s value as part of the form data, when that button is used to submit the form. |
| 38 | + */ |
| 39 | + name?: string; |
| 40 | + |
| 41 | + /** |
| 42 | + * The default behavior of the button. Possible values are: |
| 43 | + * - `submit`: The button submits the form data to the server. This is the default if the attribute is not specified for buttons associated with a <form>, or if the attribute is an empty or invalid value. |
| 44 | + * - `reset`: The button resets all the controls to their initial values, like <input type="reset">. (This behavior tends to annoy users.) |
| 45 | + * - `button`: The button has no default behavior, and does nothing when pressed by default. It can have client-side scripts listen to the element's events, which are triggered when the events occur. |
| 46 | + */ |
| 47 | + type: "submit" | "reset" | "button" = "button"; |
| 48 | + |
| 49 | + // #region @ButtonStyleButton |
| 50 | + autofocus?: boolean; |
| 51 | + style: ButtonStyle; |
| 52 | + /** |
| 53 | + * This Boolean attribute prevents the user from interacting with the button: it cannot be pressed or focused. |
| 54 | + */ |
| 55 | + disabled?: boolean; |
| 56 | + // TextManifest |
| 57 | + child: Widget; |
| 58 | + // #endregion @ButtonStyleButton |
| 59 | + |
| 60 | + constructor({ |
| 61 | + key, |
| 62 | + name, |
| 63 | + autofocus, |
| 64 | + disabled, |
| 65 | + style, |
| 66 | + child, |
| 67 | + ...rest |
| 68 | + }: { key: WidgetKey } & { |
| 69 | + name?: string; |
| 70 | + } & IButtonStyleButtonProps & |
| 71 | + IWHStyleWidget) { |
| 72 | + super({ key, ...rest }); |
| 73 | + |
| 74 | + // set button properties |
| 75 | + this.name = name; |
| 76 | + |
| 77 | + this.autofocus = autofocus; |
| 78 | + this.disabled = disabled; |
| 79 | + this.style = style; |
| 80 | + this.child = child; |
9 | 81 |
|
10 | | - children = [ |
11 | 82 | // |
12 | | - ]; |
| 83 | + this.children = this.makechildren(); |
| 84 | + } |
| 85 | + |
| 86 | + makechildren() { |
| 87 | + if (this.child instanceof Text) { |
| 88 | + return [ |
| 89 | + <StylableJsxWidget>{ |
| 90 | + key: new WidgetKey(`${this.key.id}.text`, "text"), |
| 91 | + styleData: () => null, |
| 92 | + jsxConfig: () => { |
| 93 | + return <JSXElementConfig>{ |
| 94 | + type: "static-tree", |
| 95 | + tree: JSX.text((this.child as Text).data as string), |
| 96 | + }; |
| 97 | + }, |
| 98 | + }, |
| 99 | + ]; |
| 100 | + } |
| 101 | + |
| 102 | + return []; |
| 103 | + } |
| 104 | + |
| 105 | + styleData(): ElementCssStyleData { |
| 106 | + const containerstyle = super.styleData(); |
| 107 | + |
| 108 | + // wip |
| 109 | + return { |
| 110 | + // general layouts, continer --------------------- |
| 111 | + ...containerstyle, |
| 112 | + // ----------------------------------------------- |
| 113 | + |
| 114 | + // padding |
| 115 | + ...css.padding(this.style.padding?.default), |
| 116 | + "box-sizing": (this.padding && "border-box") || undefined, |
13 | 117 |
|
14 | | - styleData() { |
15 | | - return {}; |
| 118 | + // background |
| 119 | + "background-color": this.style.backgroundColor |
| 120 | + ? css.color(this.style.backgroundColor.default) |
| 121 | + : undefined, |
| 122 | + |
| 123 | + // text styles -------------------------------------------- |
| 124 | + color: css.color((this.style.textStyle.default as ITextStyle)?.color), |
| 125 | + // "text-overflow": this.overflow, |
| 126 | + "font-size": css.px(this.style.textStyle.default.fontSize), |
| 127 | + "font-family": css.fontFamily(this.style.textStyle.default.fontFamily), |
| 128 | + "font-weight": css.convertToCssFontWeight( |
| 129 | + this.style.textStyle.default.fontWeight |
| 130 | + ), |
| 131 | + // "word-spacing": this.style.wordSpacing, |
| 132 | + "letter-spacing": css.letterSpacing( |
| 133 | + this.style.textStyle.default.letterSpacing |
| 134 | + ), |
| 135 | + "line-height": css.length(this.style.textStyle.default.lineHeight), |
| 136 | + // "text-align": this.textAlign, |
| 137 | + "text-decoration": css.textDecoration( |
| 138 | + this.style.textStyle.default.decoration |
| 139 | + ), |
| 140 | + "text-shadow": css.textShadow(this.style.textStyle.default.textShadow), |
| 141 | + "text-transform": css.textTransform( |
| 142 | + this.style.textStyle.default.textTransform |
| 143 | + ), |
| 144 | + // text styles -------------------------------------------- |
| 145 | + |
| 146 | + // |
| 147 | + width: undefined, // clear fixed width |
| 148 | + "min-width": css.length(this.minWidth), |
| 149 | + "min-height": css.length(this.minHeight), |
| 150 | + |
| 151 | + border: containerstyle["border"] ?? "none", |
| 152 | + outline: containerstyle["outline"] ?? "none", |
| 153 | + |
| 154 | + // button cursor |
| 155 | + cursor: "pointer", |
| 156 | + |
| 157 | + ":hover": _button_hover_style, |
| 158 | + ":disabled": _button_disabled_style, |
| 159 | + ":active": _button_active_style, |
| 160 | + ":focus": _button_focus_style, |
| 161 | + }; |
16 | 162 | } |
17 | 163 |
|
| 164 | + // @ts-ignore |
18 | 165 | jsxConfig() { |
19 | 166 | return <JSXElementConfig>{ |
20 | 167 | tag: JSX.identifier("button"), |
21 | 168 | attributes: [ |
22 | | - new JSXAttribute( |
23 | | - "onClick", |
24 | | - Snippet.fromStatic("() => { alert(`button click`) }") |
25 | | - ), |
| 169 | + // wip |
| 170 | + // TODO: this only works for React. (wont' work for vanilla html) |
| 171 | + // new JSXAttribute( |
| 172 | + // "onClick", |
| 173 | + // JSX.exp( |
| 174 | + // // Snippet.fromStatic() |
| 175 | + // // TODO: type check |
| 176 | + // "() => { /* add onclick callback */ }" as any |
| 177 | + // ) |
| 178 | + // ), |
26 | 179 | ], |
27 | 180 | }; |
28 | 181 | } |
| 182 | + |
| 183 | + get finalStyle() { |
| 184 | + const superstyl = super.finalStyle; |
| 185 | + |
| 186 | + // width override. ------------------------------------------------------------------------------------------ |
| 187 | + return { |
| 188 | + ...superstyl, |
| 189 | + width: undefined, |
| 190 | + }; |
| 191 | + // ---------------------------------------------------------------------------------------------------------- |
| 192 | + } |
29 | 193 | } |
| 194 | + |
| 195 | +const _button_hover_style: CSSProperties = { |
| 196 | + opacity: 0.8, |
| 197 | +}; |
| 198 | + |
| 199 | +const _button_disabled_style: CSSProperties = { |
| 200 | + opacity: 0.5, |
| 201 | +}; |
| 202 | + |
| 203 | +const _button_active_style: CSSProperties = { |
| 204 | + opacity: 1, |
| 205 | +}; |
| 206 | + |
| 207 | +const _button_focus_style: CSSProperties = {}; |
0 commit comments