bestax-mcp 1.18.6 → 1.18.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/data/bulma-classes.json +75 -3
  2. package/data/catalog.json +4 -4
  3. package/data/components/Autocomplete.json +3 -3
  4. package/data/components/Card.json +5 -5
  5. package/data/components/Carousel.json +2 -2
  6. package/data/components/Checkbox.json +1 -0
  7. package/data/components/Checkboxes.json +4 -3
  8. package/data/components/DateInput.json +9 -9
  9. package/data/components/DateTimeInput.json +8 -8
  10. package/data/components/File.json +4 -3
  11. package/data/components/Input.json +17 -13
  12. package/data/components/Message.json +4 -4
  13. package/data/components/Modal.json +30 -11
  14. package/data/components/Numberinput.json +4 -3
  15. package/data/components/PinInput.json +1 -0
  16. package/data/components/Radio.json +6 -1
  17. package/data/components/Radios.json +4 -3
  18. package/data/components/Rate.json +3 -3
  19. package/data/components/Select.json +7 -5
  20. package/data/components/Skeleton.json +11 -11
  21. package/data/components/Slider.json +4 -3
  22. package/data/components/Switch.json +1 -0
  23. package/data/components/Taginput.json +3 -3
  24. package/data/components/TextArea.json +3 -3
  25. package/data/components/Theme.json +8 -4
  26. package/data/components/TimeInput.json +10 -10
  27. package/data/components/classNames.json +6 -6
  28. package/data/components/useBulmaClasses.json +520 -15
  29. package/data/skills/bestax-icons/references/icon-libraries.md +14 -1
  30. package/data/skills/bestax-migrate/SKILL.md +10 -4
  31. package/data/skills/bestax-migrate/references/bloomer/unmappables.md +4 -1
  32. package/data/skills/bestax-migrate/references/bulma-classes/component-map.md +49 -15
  33. package/data/skills/bestax-migrate/references/bulma-classes/unmappables.md +136 -26
  34. package/data/skills/bestax-theming/SKILL.md +13 -10
  35. package/data/skills/bestax-theming/examples/dark-mode.tsx +7 -6
  36. package/data/skills/bestax-theming/examples/theme-config.tsx +10 -3
  37. package/data/skills/bestax-theming/references/css-variables.md +49 -11
  38. package/data/skills.json +7 -7
  39. package/dist/bulma-classes.d.ts +45 -0
  40. package/dist/bulma-classes.d.ts.map +1 -1
  41. package/dist/bulma-classes.js +183 -28
  42. package/dist/data.d.ts +11 -0
  43. package/dist/data.d.ts.map +1 -1
  44. package/dist/format.d.ts.map +1 -1
  45. package/dist/format.js +7 -1
  46. package/dist/helper-props.d.ts +6 -0
  47. package/dist/helper-props.d.ts.map +1 -1
  48. package/dist/helper-props.js +3 -2
  49. package/dist/search.d.ts +18 -1
  50. package/dist/search.d.ts.map +1 -1
  51. package/dist/search.js +185 -1
  52. package/dist/server.d.ts.map +1 -1
  53. package/dist/server.js +44 -3
  54. package/dist/version.d.ts +15 -6
  55. package/dist/version.d.ts.map +1 -1
  56. package/dist/version.js +40 -3
  57. package/package.json +2 -2
@@ -3197,7 +3197,7 @@
3197
3197
  "textColor": null,
3198
3198
  "bgColor": null,
3199
3199
  "part": false,
3200
- "why": "bestax `Checkbox` renders its own styled markup, not Bulma's",
3200
+ "why": "bestax `Checkbox` renders its own styled markup, not Bulma's. Write it by hand in place of the element that carries `.checkbox`, Bulma's `<label>` or a bare `<input>`, with the `<input>`'s attributes on it: `id`, `name`, `aria-label` and the rest reach its `<input>`, and a `<label>`'s text is its children. Drive it with `checked` and `onChange`, and add `indeterminate` for a select-all box. Its `className` goes on its `<label>`, which declares the `--bulma-checkbox-*` variables, so set the page's colors with those in a rule for your class beside `.styled-checkbox`. Where the page put `.checkbox` on a bare `<input>`, drop its own rules for that box, since bestax draws its own and `.checkbox` is on its `<label>` now",
3201
3201
  "modifiers": {},
3202
3202
  "omits": {},
3203
3203
  "wrapsChildren": null,
@@ -3658,7 +3658,10 @@
3658
3658
  "is-medium": { "writes": [{ "prop": "size", "value": "medium" }] },
3659
3659
  "is-large": { "writes": [{ "prop": "size", "value": "large" }] }
3660
3660
  },
3661
- "omits": {},
3661
+ "omits": {
3662
+ "is-left": "Bulma places it inside a `.control` with `has-icons-left`, and bestax `Control` renders that icon itself from `iconLeft` (`iconLeft={{ library: \"fa\", name: \"envelope\", size: \"small\" }}`), after its children, so a hidden `.icon` there can go as that prop; on `Icon` the class stays in `className`, which renders the same",
3663
+ "is-right": "Bulma places it inside a `.control` with `has-icons-right`, and bestax `Control` renders that icon itself from `iconRight` (`iconRight={{ library: \"fa\", name: \"envelope\", size: \"small\" }}`), after its children, so a hidden `.icon` there can go as that prop; on `Icon` the class stays in `className`, which renders the same"
3664
+ },
3662
3665
  "wrapsChildren": null,
3663
3666
  "folds": null,
3664
3667
  "absorbs": null,
@@ -13062,5 +13065,74 @@
13062
13065
  "theme-dark",
13063
13066
  "theme-light",
13064
13067
  "title"
13065
- ]
13068
+ ],
13069
+ "elsewhere": [
13070
+ {
13071
+ "why": "a Font Awesome class: Font Awesome's own stylesheet styles it, not Bulma's, so keep loading Font Awesome (the bestax-migrate skill's `html-asset:font-awesome` says how). bestax `Icon` writes these classes from its props, on the <i> it renders inside a `.icon`",
13072
+ "match": "^(?:fa|fa[srbldt]|fa-[a-z0-9]+(?:-[a-z0-9]+)*|svg-inline--fa)$",
13073
+ "glyph": true
13074
+ },
13075
+ {
13076
+ "why": "a Material Design Icons class: its own stylesheet styles it, not Bulma's, so keep loading it. bestax `Icon` writes these classes from its props, with `library=\"mdi\"`, on the <i> it renders inside a `.icon`",
13077
+ "match": "^mdi(?:-[a-z0-9]+)*$",
13078
+ "glyph": true
13079
+ },
13080
+ {
13081
+ "why": "a bulma-social class, a Bulma extension's brand color for Bulma's `.button`, which bestax's `Button` renders: keep loading bulma-social and keep the class on `Button` in `className`, since bestax has no component for it (the bestax-migrate skill's `html-asset:bulma-extension` has the recipe)",
13082
+ "match": "^is-(?:apple|bitbucket|discord|dropbox|facebook|flickr|foursquare|github|gitlab|instagram|linkedin|microsoft|odnoklassniki|openid|pinterest|reddit|slack|soundcloud|tumblr|twitch|twitter|vimeo|vk|x|yahoo|youtube|animated)$",
13083
+ "glyph": false
13084
+ },
13085
+ {
13086
+ "why": "a bulma-social helper, a Bulma extension's text or background color in a brand's color, with `-dark` and `-light` for its shades: keep loading bulma-social and keep the class in `className` on the element that has it, since bestax has no prop for it (the bestax-migrate skill's `html-asset:bulma-extension` has the recipe, and the brand's own stylesheet holds it)",
13087
+ "match": "^has-(?:text|background)-(?:apple|bitbucket|discord|dropbox|facebook|flickr|foursquare|github|gitlab|instagram|linkedin|microsoft|odnoklassniki|openid|pinterest|reddit|slack|soundcloud|tumblr|twitch|twitter|vimeo|vk|x|yahoo|youtube)(?:-dark|-light)?$",
13088
+ "glyph": false
13089
+ },
13090
+ {
13091
+ "why": "a bulma-carousel class, a Bulma extension bestax's `Carousel` does the job of (the bestax-migrate skill's `html-asset:bulma-extension` says how). Once the page stops loading bulma-carousel nothing styles it: `is-covered`'s `object-fit: cover` on a slide's image goes in the app's own CSS",
13092
+ "match": "^(?:has-carousel|hero-carousel|is-background|is-covered|slider-(?:container|item|navigation-next|navigation-previous|page|pagination)|video-container)$",
13093
+ "glyph": false
13094
+ }
13095
+ ],
13096
+ "ownClasses": {
13097
+ "autocomplete": "Autocomplete",
13098
+ "avatar": "Avatar",
13099
+ "avatars": "Avatars",
13100
+ "badge": "Badge",
13101
+ "carousel": "Carousel",
13102
+ "styled-checkbox": "Checkbox",
13103
+ "collapse": "Collapse",
13104
+ "collapses": "Collapses",
13105
+ "combobox": "Combobox",
13106
+ "context-menu": "ContextMenu",
13107
+ "daterangeinput": "DateRangeInput",
13108
+ "dialog": "Dialog",
13109
+ "empty-state": "EmptyState",
13110
+ "hover-card": "HoverCard",
13111
+ "kbd": "Kbd",
13112
+ "link-button": "LinkButton",
13113
+ "loading": "Loading",
13114
+ "numberinput": "Numberinput",
13115
+ "pin-input": "PinInput",
13116
+ "popover": "Popover",
13117
+ "styled-radio": "Radio",
13118
+ "rate": "Rate",
13119
+ "reveal": "Reveal",
13120
+ "sidebar": "Sidebar",
13121
+ "slider": "Slider",
13122
+ "steps": "Steps",
13123
+ "switch": "Switch",
13124
+ "taginput": "Taginput",
13125
+ "timeline": "Timeline",
13126
+ "toast": "Toast",
13127
+ "tooltip": "Tooltip",
13128
+ "tree-view": "TreeView"
13129
+ },
13130
+ "byHand": {
13131
+ "thead": { "target": "Table.Thead", "props": [] },
13132
+ "tbody": { "target": "Table.Tbody", "props": [] },
13133
+ "tfoot": { "target": "Table.Tfoot", "props": [] },
13134
+ "tr": { "target": "Table.Tr", "props": ["isSelected", "color"] },
13135
+ "th": { "target": "Table.Th", "props": ["isAligned", "width", "color"] },
13136
+ "td": { "target": "Table.Td", "props": ["isAligned", "color"] }
13137
+ }
13066
13138
  }
package/data/catalog.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 2,
3
3
  "generatedFrom": {
4
4
  "package": "@allxsmith/bestax-bulma",
5
- "version": "5.45.0"
5
+ "version": "5.46.0"
6
6
  },
7
7
  "docsBase": "https://bestax.io/docs",
8
8
  "categories": [
@@ -641,7 +641,7 @@
641
641
  "import": "import { Input, Field, Control, Button, Select, Icon } from '@allxsmith/bestax-bulma';",
642
642
  "compound": false,
643
643
  "propCount": 29,
644
- "exampleCount": 30
644
+ "exampleCount": 31
645
645
  },
646
646
  {
647
647
  "name": "Kbd",
@@ -905,7 +905,7 @@
905
905
  "import": "import { Radio, Radios, Control } from '@allxsmith/bestax-bulma';",
906
906
  "compound": false,
907
907
  "propCount": 7,
908
- "exampleCount": 5
908
+ "exampleCount": 6
909
909
  },
910
910
  {
911
911
  "name": "Radios",
@@ -1136,7 +1136,7 @@
1136
1136
  "import": "import { Theme } from '@allxsmith/bestax-bulma';",
1137
1137
  "compound": false,
1138
1138
  "propCount": 43,
1139
- "exampleCount": 12
1139
+ "exampleCount": 13
1140
1140
  },
1141
1141
  {
1142
1142
  "name": "TimeInput",
@@ -42,15 +42,15 @@
42
42
  "code": "function example() {\n const fruits = [\n 'Apple',\n 'Apricot',\n 'Avocado',\n 'Banana',\n 'Blackberry',\n 'Blueberry',\n ];\n\n return (\n <Autocomplete data={fruits} placeholder=\"Type to filter...\" keepFirst />\n );\n}"
43
43
  },
44
44
  {
45
- "title": "Context-Aware Rendering",
45
+ "title": "Context-Aware Rendering › Default (with label)",
46
46
  "code": "<Autocomplete\n label=\"Fruit\"\n data={['Apple', 'Banana', 'Cherry']}\n placeholder=\"Search fruit...\"\n/>"
47
47
  },
48
48
  {
49
- "title": "Context-Aware Rendering",
49
+ "title": "Context-Aware Rendering › With Field Wrapper",
50
50
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Fruit\"\n labelProps={{ htmlFor: 'fruit-field', id: 'fruit-field-label' }}\n >\n <Field.Body>\n <Field>\n <Autocomplete\n id=\"fruit-field\"\n data={['Apple', 'Banana', 'Cherry']}\n placeholder=\"Search fruit...\"\n />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
51
51
  },
52
52
  {
53
- "title": "Context-Aware Rendering",
53
+ "title": "Context-Aware Rendering › With Field and Control Wrappers",
54
54
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Fruit\"\n labelProps={{\n htmlFor: 'fruit-field-control',\n id: 'fruit-field-control-label',\n }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"search\">\n <Autocomplete\n id=\"fruit-field-control\"\n data={['Apple', 'Banana', 'Cherry']}\n placeholder=\"Search fruit...\"\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
55
55
  }
56
56
  ],
@@ -42,23 +42,23 @@
42
42
  "code": "<Card\n header=\"Upgrade to Pro\"\n headerIcon={\n <button className=\"card-header-icon\">\n <Icon library=\"fa\" name=\"bolt\" textColor=\"warning\" ariaLabel=\"Pro\" />\n </button>\n }\n image=\"https://images.unsplash.com/photo-1551288049-bebda4e38f71?auto=format&fit=crop&w=600&q=80\"\n imageAlt=\"Dashboard analytics\"\n m=\"3\"\n textAlign=\"centered\"\n hasShadow\n footer={[\n <Button key=\"upgrade\" color=\"success\">\n Upgrade Now\n </Button>,\n <Button key=\"learn\" color=\"info\" isOutlined>\n Learn More\n </Button>,\n ]}\n>\n Unlock advanced analytics, priority support, and unlimited exports for your\n team.\n</Card>"
43
43
  },
44
44
  {
45
- "title": "Compound (dot-notation) usage",
45
+ "title": "Compound (dot-notation) usage › Complete Card with Compound Components",
46
46
  "code": "import { Icon, Image } from '@allxsmith/bestax-bulma';\n\n<Card>\n <Card.Header>\n <Card.Header.Title>Compound Component Card</Card.Header.Title>\n <Card.Header.Icon aria-label=\"more options\">\n <Icon name=\"angle-down\" variant=\"solid\" ariaLabel=\"expand\" />\n </Card.Header.Icon>\n </Card.Header>\n <Card.Image>\n <Image\n src=\"https://images.unsplash.com/photo-1506744038136-46273834b3fb?auto=format&fit=crop&w=600&q=80\"\n alt=\"Beautiful forest\"\n size=\"4by3\"\n />\n </Card.Image>\n <Card.Content>\n <Content>\n This card is built using compound components for maximum flexibility.\n </Content>\n </Card.Content>\n <Card.Footer>\n <Card.FooterItem>\n <Button color=\"primary\">Save</Button>\n </Card.FooterItem>\n <Card.FooterItem>\n <Button>Cancel</Button>\n </Card.FooterItem>\n </Card.Footer>\n</Card>;"
47
47
  },
48
48
  {
49
- "title": "Compound (dot-notation) usage",
49
+ "title": "Compound (dot-notation) usage › Minimal Compound Card",
50
50
  "code": "<Card>\n <Card.Header>\n <Card.Header.Title>Simple Header</Card.Header.Title>\n </Card.Header>\n <Card.Content>\n <Paragraph>Just some minimal content using compound components.</Paragraph>\n </Card.Content>\n</Card>"
51
51
  },
52
52
  {
53
- "title": "Compound (dot-notation) usage",
53
+ "title": "Compound (dot-notation) usage › Card Header with Icon",
54
54
  "code": "function ExpandableCard() {\n const [isOpen, setIsOpen] = React.useState(true);\n\n return (\n <Card>\n <Card.Header>\n <Card.Header.Title>Expandable Card</Card.Header.Title>\n <Card.Header.Icon\n aria-label={isOpen ? 'collapse' : 'expand'}\n onClick={() => setIsOpen(!isOpen)}\n >\n <Icon\n library=\"fa\"\n name={isOpen ? 'angle-up' : 'angle-down'}\n ariaLabel={isOpen ? 'collapse' : 'expand'}\n />\n </Card.Header.Icon>\n </Card.Header>\n {isOpen && (\n <Card.Content>\n This card uses React state to toggle content visibility. Click the\n icon in the header to expand or collapse this section.\n </Card.Content>\n )}\n </Card>\n );\n}"
55
55
  },
56
56
  {
57
- "title": "Compound (dot-notation) usage",
57
+ "title": "Compound (dot-notation) usage › Mixed Approach",
58
58
  "code": "<Card header=\"Prop-based header\" textColor=\"primary\" m=\"3\">\n <Card.Content bgColor=\"light\">\n <Paragraph>\n You can mix prop-based and compound component approaches!\n </Paragraph>\n </Card.Content>\n <Card.Footer>\n <Card.FooterItem>Mixed approach example</Card.FooterItem>\n </Card.Footer>\n</Card>"
59
59
  },
60
60
  {
61
- "title": "Compound (dot-notation) usage",
61
+ "title": "Compound (dot-notation) usage › Bulma's Own Markup (`p` Title, `a` Footer Items)",
62
62
  "code": "<Card>\n <Card.Header>\n <Card.Header.Title as=\"p\">Component</Card.Header.Title>\n </Card.Header>\n <Card.Content>Card content goes here.</Card.Content>\n <Card.Footer>\n <Card.FooterItem as=\"a\" href=\"#save\">\n Save\n </Card.FooterItem>\n <Card.FooterItem as=\"a\" href=\"#edit\">\n Edit\n </Card.FooterItem>\n </Card.Footer>\n</Card>"
63
63
  }
64
64
  ],
@@ -14,11 +14,11 @@
14
14
  "code": "<Carousel itemsToShow={1} itemsToShowTablet={2} itemsToShowDesktop={3}>\n {[\n 'Garden Room',\n 'Harbor Suite',\n 'Loft',\n 'Courtyard Twin',\n 'Terrace Room',\n 'Family Suite',\n ].map(room => (\n <CarouselItem key={room}>\n <Card m=\"2\">\n <Card.Content>\n <Title as=\"p\" size=\"5\">\n {room}\n </Title>\n <SubTitle as=\"p\" size=\"6\">\n Sleeps two\n </SubTitle>\n </Card.Content>\n </Card>\n </CarouselItem>\n ))}\n</Carousel>"
15
15
  },
16
16
  {
17
- "title": "Several Items in View",
17
+ "title": "Several Items in View › Stepping and indicators",
18
18
  "code": "<Carousel itemsToShow={3} itemsToScroll={3} repeat={false}>\n {[1, 2, 3, 4, 5, 6, 7].map(n => (\n <CarouselItem key={n}>\n <Box m=\"2\" textAlign=\"centered\">\n Item {n}\n </Box>\n </CarouselItem>\n ))}\n</Carousel>"
19
19
  },
20
20
  {
21
- "title": "Several Items in View",
21
+ "title": "Several Items in View › Spacing between items",
22
22
  "code": "<Carousel className=\"room-gallery\" itemsToShow={3}>\n {/* items */}\n</Carousel>"
23
23
  },
24
24
  {
@@ -127,6 +127,7 @@
127
127
  ],
128
128
  "extraProps": [],
129
129
  "catchAll": "All standard <input> attributes and Bulma helper props",
130
+ "helperPropsNote": "Helper props go on the outer `<label>`, with `className`. The other attributes go on the `<input>`.",
130
131
  "types": []
131
132
  }
132
133
  ],
@@ -10,15 +10,15 @@
10
10
  "code": "<Checkboxes>\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n <Checkbox> Feed the pet </Checkbox>\n <Checkbox> Take out the trash </Checkbox>\n <Checkbox> Clean your room </Checkbox>\n <Checkbox> Set the table </Checkbox>\n <Checkbox> Help with dishes </Checkbox>\n <Checkbox> Water the plants </Checkbox>\n <Checkbox> Put away toys </Checkbox>\n</Checkboxes>"
11
11
  },
12
12
  {
13
- "title": "Context-Aware Rendering",
13
+ "title": "Context-Aware Rendering › Default (with label)",
14
14
  "code": "<Checkboxes label=\"Chores\">\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n</Checkboxes>"
15
15
  },
16
16
  {
17
- "title": "Context-Aware Rendering",
17
+ "title": "Context-Aware Rendering › With Field Wrapper",
18
18
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Chores\"\n labelProps={{ id: 'chores-label', htmlFor: undefined }}\n >\n <Field.Body>\n <Field>\n <Checkboxes aria-labelledby=\"chores-label\">\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n </Checkboxes>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
19
19
  },
20
20
  {
21
- "title": "Context-Aware Rendering",
21
+ "title": "Context-Aware Rendering › With Field and Control Wrappers",
22
22
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Chores\"\n labelProps={{ id: 'chores-label-control', htmlFor: undefined }}\n >\n <Field.Body>\n <Field>\n <Control>\n <Checkboxes aria-labelledby=\"chores-label-control\">\n <Checkbox> Make the bed </Checkbox>\n <Checkbox> Brush teeth </Checkbox>\n <Checkbox> Do homework </Checkbox>\n </Checkboxes>\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
23
23
  },
24
24
  {
@@ -242,6 +242,7 @@
242
242
  ],
243
243
  "extraProps": [],
244
244
  "catchAll": "All standard <input> attributes and Bulma helper props",
245
+ "helperPropsNote": "Helper props go on the outer `<label>`, with `className`. The other attributes go on the `<input>`.",
245
246
  "types": []
246
247
  }
247
248
  ],
@@ -86,27 +86,27 @@
86
86
  "code": "<Field label=\"Date\">\n <Control iconLeftName=\"calendar\" isLoading>\n <DateInput placeholder=\"YYYY-MM-DD\" />\n </Control>\n</Field>"
87
87
  },
88
88
  {
89
- "title": "Manual Keyboard Entry",
89
+ "title": "Manual Keyboard Entry › Basic",
90
90
  "code": "function example() {\n return (\n <DateInput\n label=\"Click in, then arrow or type\"\n defaultValue={new Date(2024, 5, 7)}\n openOnFocus={false}\n />\n );\n}"
91
91
  },
92
92
  {
93
- "title": "Manual Keyboard Entry",
93
+ "title": "Manual Keyboard Entry › Digit entry and auto-advance",
94
94
  "code": "function example() {\n return (\n <DateInput\n label=\"Type digits — auto-advance across segments\"\n defaultValue={new Date(2024, 5, 7)}\n openOnFocus={false}\n />\n );\n}"
95
95
  },
96
96
  {
97
- "title": "Manual Keyboard Entry",
97
+ "title": "Manual Keyboard Entry › Controlled with live value",
98
98
  "code": "function example() {\n const [v, setV] = useState<Date | null>(() => new Date(2024, 5, 7));\n return (\n <Block>\n <DateInput\n label=\"Arrow or type — value updates live\"\n value={v}\n onChange={setV}\n openOnFocus={false}\n />\n <Paragraph mt=\"2\">Selected: {v ? v.toDateString() : '—'}</Paragraph>\n </Block>\n );\n}"
99
99
  },
100
100
  {
101
- "title": "Manual Keyboard Entry",
101
+ "title": "Manual Keyboard Entry › Free-form fallback",
102
102
  "code": "function example() {\n return (\n <DateInput\n label=\"Free-form (Intl format)\"\n format={{ year: 'numeric', month: 'long', day: 'numeric' }}\n defaultValue={new Date(2024, 5, 7)}\n openOnFocus={false}\n />\n );\n}"
103
103
  },
104
104
  {
105
- "title": "Picker vs Input Modes",
105
+ "title": "Picker vs Input Modes › Picker only",
106
106
  "code": "<DateInput label=\"Picker only\" editable={false} defaultValue={new Date()} />"
107
107
  },
108
108
  {
109
- "title": "Picker vs Input Modes",
109
+ "title": "Picker vs Input Modes › Input only",
110
110
  "code": "<DateInput label=\"Input only\" popover={false} defaultValue={new Date()} />"
111
111
  },
112
112
  {
@@ -162,15 +162,15 @@
162
162
  "code": "<DateInput\n label=\"Date of birth\"\n horizontal\n placeholder=\"YYYY-MM-DD\"\n openOnFocus={false}\n/>"
163
163
  },
164
164
  {
165
- "title": "Context-Aware Rendering",
165
+ "title": "Context-Aware Rendering › Default (with label)",
166
166
  "code": "<DateInput label=\"Date\" placeholder=\"YYYY-MM-DD\" />"
167
167
  },
168
168
  {
169
- "title": "Context-Aware Rendering",
169
+ "title": "Context-Aware Rendering › With Field Wrapper",
170
170
  "code": "function example() {\n return (\n <Field horizontal label=\"Date\" labelProps={{ htmlFor: 'date-field' }}>\n <Field.Body>\n <Field>\n <DateInput id=\"date-field\" placeholder=\"YYYY-MM-DD\" />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
171
171
  },
172
172
  {
173
- "title": "Context-Aware Rendering",
173
+ "title": "Context-Aware Rendering › With Field and Control Wrappers",
174
174
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Date\"\n labelProps={{ htmlFor: 'date-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"calendar-alt\">\n <DateInput id=\"date-field-control\" placeholder=\"YYYY-MM-DD\" />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
175
175
  }
176
176
  ],
@@ -138,35 +138,35 @@
138
138
  "code": "<Block display=\"flex\" flexDirection=\"column\">\n <DateTimeInput label=\"Disabled\" disabled />\n <DateTimeInput label=\"Read only\" readOnly defaultValue={new Date()} />\n <DateTimeInput label=\"Loading\" isLoading />\n</Block>"
139
139
  },
140
140
  {
141
- "title": "Context-Aware Rendering",
141
+ "title": "Context-Aware Rendering › Default (with label)",
142
142
  "code": "<DateTimeInput label=\"When\" placeholder=\"YYYY-MM-DD HH:MM\" />"
143
143
  },
144
144
  {
145
- "title": "Context-Aware Rendering",
145
+ "title": "Context-Aware Rendering › With Field Wrapper",
146
146
  "code": "function example() {\n return (\n <Field horizontal label=\"When\" labelProps={{ htmlFor: 'when-field' }}>\n <Field.Body>\n <Field>\n <DateTimeInput id=\"when-field\" placeholder=\"YYYY-MM-DD HH:MM\" />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
147
147
  },
148
148
  {
149
- "title": "Context-Aware Rendering",
149
+ "title": "Context-Aware Rendering › With Field and Control Wrappers",
150
150
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"When\"\n labelProps={{ htmlFor: 'when-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"calendar-alt\">\n <DateTimeInput\n id=\"when-field-control\"\n placeholder=\"YYYY-MM-DD HH:MM\"\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
151
151
  },
152
152
  {
153
- "title": "Manual Keyboard Entry",
153
+ "title": "Manual Keyboard Entry › Basic",
154
154
  "code": "function example() {\n return (\n <DateTimeInput\n label=\"Type across date and time\"\n defaultValue={new Date(2024, 5, 7, 13, 45)}\n openOnFocus={false}\n />\n );\n}"
155
155
  },
156
156
  {
157
- "title": "Manual Keyboard Entry",
157
+ "title": "Manual Keyboard Entry › Controlled with live value",
158
158
  "code": "function example() {\n const [v, setV] = useState<Date | null>(() => new Date(2024, 5, 7, 13, 45));\n return (\n <Block>\n <DateTimeInput\n label=\"Arrow or type — value updates live\"\n value={v}\n onChange={setV}\n openOnFocus={false}\n />\n <Paragraph mt=\"2\">Selected: {v ? v.toString() : '—'}</Paragraph>\n </Block>\n );\n}"
159
159
  },
160
160
  {
161
- "title": "Manual Keyboard Entry",
161
+ "title": "Manual Keyboard Entry › Free-form fallback",
162
162
  "code": "function example() {\n return (\n <DateTimeInput\n label=\"Free-form (Intl format)\"\n format={{ dateStyle: 'medium', timeStyle: 'short' }}\n defaultValue={new Date(2024, 5, 7, 13, 45)}\n openOnFocus={false}\n />\n );\n}"
163
163
  },
164
164
  {
165
- "title": "Picker vs Input Modes",
165
+ "title": "Picker vs Input Modes › Picker only",
166
166
  "code": "<DateTimeInput label=\"Picker only\" editable={false} defaultValue={new Date()} />"
167
167
  },
168
168
  {
169
- "title": "Picker vs Input Modes",
169
+ "title": "Picker vs Input Modes › Input only",
170
170
  "code": "<DateTimeInput label=\"Input only\" popover={false} defaultValue={new Date()} />"
171
171
  }
172
172
  ],
@@ -62,15 +62,15 @@
62
62
  "code": "<File\n color=\"primary\"\n isRight\n hasName\n fileName=\"right.pdf\"\n buttonLabel=\"Choose a file…\"\n iconLeft={<Icon name=\"upload\" aria-hidden=\"true\" />}\n/>"
63
63
  },
64
64
  {
65
- "title": "Context-Aware Rendering",
65
+ "title": "Context-Aware Rendering › Default (with label)",
66
66
  "code": "<File\n label=\"Document\"\n buttonLabel=\"Choose a file…\"\n iconLeft={<Icon name=\"upload\" aria-hidden=\"true\" />}\n/>"
67
67
  },
68
68
  {
69
- "title": "Context-Aware Rendering",
69
+ "title": "Context-Aware Rendering › With Field Wrapper",
70
70
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Document\"\n labelProps={{ htmlFor: 'document-field' }}\n >\n <Field.Body>\n <Field>\n <File\n id=\"document-field\"\n buttonLabel=\"Choose a file…\"\n iconLeft={<Icon name=\"upload\" aria-hidden=\"true\" />}\n />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
71
71
  },
72
72
  {
73
- "title": "Context-Aware Rendering",
73
+ "title": "Context-Aware Rendering › With Field and Control Wrappers",
74
74
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Document\"\n labelProps={{ htmlFor: 'document-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"paperclip\">\n <File\n id=\"document-field-control\"\n buttonLabel=\"Choose a file…\"\n iconLeft={<Icon name=\"upload\" aria-hidden=\"true\" />}\n />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
75
75
  }
76
76
  ],
@@ -298,6 +298,7 @@
298
298
  ],
299
299
  "extraProps": [],
300
300
  "catchAll": "All standard <input> attributes and Bulma helper props",
301
+ "helperPropsNote": "Helper props go on the `.file` wrapper `<div>`, with `className`. The other attributes go on the `<input>`.",
301
302
  "types": []
302
303
  }
303
304
  ],
@@ -50,23 +50,27 @@
50
50
  "code": "<>\n <Input\n label=\"Username\"\n color=\"success\"\n value=\"bulma\"\n message=\"This username is available\"\n messageColor=\"success\"\n iconLeftName=\"user\"\n iconRightName=\"check\"\n onChange={() => {}}\n />\n <Input\n label=\"Email\"\n type=\"email\"\n color=\"danger\"\n value=\"hello@\"\n message=\"This email is invalid\"\n messageColor=\"danger\"\n iconLeftName=\"envelope\"\n iconRightName=\"exclamation-triangle\"\n onChange={() => {}}\n />\n</>"
51
51
  },
52
52
  {
53
- "title": "Form Addons",
53
+ "title": "Visually Hidden Label for Screen Readers",
54
+ "code": "<Input\n label=\"Email\"\n labelProps={{ className: 'is-sr-only' }}\n type=\"email\"\n placeholder=\"you@example.com\"\n/>"
55
+ },
56
+ {
57
+ "title": "Form Addons › Input + Button",
54
58
  "code": "<Field hasAddons>\n <Control isExpanded>\n <Input placeholder=\"Find a repository\" aria-label=\"Find a repository\" />\n </Control>\n <Control>\n <Button color=\"info\">Search</Button>\n </Control>\n</Field>"
55
59
  },
56
60
  {
57
- "title": "Form Addons",
61
+ "title": "Form Addons › Input + Static Suffix",
58
62
  "code": "<Field hasAddons>\n <Control isExpanded>\n <Input placeholder=\"Your email\" aria-label=\"Email username\" />\n </Control>\n <Control>\n <Button isStatic>@gmail.com</Button>\n </Control>\n</Field>"
59
63
  },
60
64
  {
61
- "title": "Form Addons",
65
+ "title": "Form Addons › Select + Input + Button",
62
66
  "code": "<Field hasAddons>\n <Control>\n <Select aria-label=\"Country code\">\n <option>+1</option>\n <option>+44</option>\n <option>+33</option>\n </Select>\n </Control>\n <Control isExpanded>\n <Input\n type=\"tel\"\n placeholder=\"Your phone number\"\n aria-label=\"Phone number\"\n />\n </Control>\n <Control>\n <Button color=\"primary\">Call</Button>\n </Control>\n</Field>"
63
67
  },
64
68
  {
65
- "title": "Form Addons",
69
+ "title": "Form Addons › Centered Addons",
66
70
  "code": "<Field hasAddons=\"centered\">\n <Control>\n <Button>Yes</Button>\n </Control>\n <Control>\n <Button>Maybe</Button>\n </Control>\n <Control>\n <Button>No</Button>\n </Control>\n</Field>"
67
71
  },
68
72
  {
69
- "title": "Form Addons",
73
+ "title": "Form Addons › Right-Aligned Addons",
70
74
  "code": "<Field hasAddons=\"right\">\n <Control>\n <Button>Yes</Button>\n </Control>\n <Control>\n <Button>Maybe</Button>\n </Control>\n <Control>\n <Button>No</Button>\n </Control>\n</Field>"
71
75
  },
72
76
  {
@@ -78,23 +82,23 @@
78
82
  "code": "function CopyButton() {\n const id = React.useId();\n const inputRef = React.useRef<HTMLInputElement>(null);\n const [status, setStatus] = useState<'idle' | 'copied' | 'failed'>('idle');\n const link = 'https://bestax.io/docs/api/form/input';\n\n // Put the button's label back after a moment.\n useEffect(() => {\n if (status !== 'copied') return undefined;\n const timer = setTimeout(() => setStatus('idle'), 2000);\n return () => clearTimeout(timer);\n }, [status]);\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(link);\n setStatus('copied');\n } catch {\n // No clipboard on this page, or the browser refused the write.\n inputRef.current?.focus();\n inputRef.current?.select();\n setStatus('failed');\n }\n };\n\n return (\n <Field label=\"Share link\" labelProps={{ htmlFor: id }}>\n <Field hasAddons>\n <Control isExpanded>\n <Input ref={inputRef} id={id} value={link} readOnly />\n </Control>\n <Control>\n <Button type=\"button\" onClick={copy}>\n <Icon\n name={status === 'copied' ? 'check' : 'copy'}\n aria-hidden=\"true\"\n />\n <span>{status === 'copied' ? 'Copied' : 'Copy'}</span>\n </Button>\n </Control>\n </Field>\n <p role=\"status\" className=\"help\">\n {status === 'copied' && 'Copied to the clipboard.'}\n </p>\n <p role=\"alert\" className=\"help is-danger\">\n {status === 'failed' &&\n \"Couldn't copy automatically. The link is selected, so copy it from the field.\"}\n </p>\n </Field>\n );\n}"
79
83
  },
80
84
  {
81
- "title": "Form Group",
85
+ "title": "Form Group › Grouped Buttons",
82
86
  "code": "<Field grouped>\n <Control>\n <Button color=\"link\">Submit</Button>\n </Control>\n <Control>\n <Button>Cancel</Button>\n </Control>\n</Field>"
83
87
  },
84
88
  {
85
- "title": "Form Group",
89
+ "title": "Form Group › Centered Group",
86
90
  "code": "<Field grouped=\"centered\">\n <Control>\n <Button color=\"link\">Submit</Button>\n </Control>\n <Control>\n <Button>Cancel</Button>\n </Control>\n</Field>"
87
91
  },
88
92
  {
89
- "title": "Form Group",
93
+ "title": "Form Group › Right-Aligned Group",
90
94
  "code": "<Field grouped=\"right\">\n <Control>\n <Button color=\"link\">Submit</Button>\n </Control>\n <Control>\n <Button>Cancel</Button>\n </Control>\n</Field>"
91
95
  },
92
96
  {
93
- "title": "Form Group",
97
+ "title": "Form Group › Expanded Input + Button",
94
98
  "code": "<Field grouped>\n <Control isExpanded>\n <Input placeholder=\"Find a repository\" aria-label=\"Find a repository\" />\n </Control>\n <Control>\n <Button color=\"info\">Search</Button>\n </Control>\n</Field>"
95
99
  },
96
100
  {
97
- "title": "Form Group",
101
+ "title": "Form Group › Multiline Group",
98
102
  "code": "<Field grouped=\"multiline\">\n {[\n 'One',\n 'Two',\n 'Three',\n 'Four',\n 'Five',\n 'Six',\n 'Seven',\n 'Eight',\n 'Nine',\n 'Ten',\n 'Eleven',\n 'Twelve',\n 'Thirteen',\n ].map(label => (\n <Control key={label}>\n <Button>{label}</Button>\n </Control>\n ))}\n</Field>"
99
103
  },
100
104
  {
@@ -114,15 +118,15 @@
114
118
  "code": "<fieldset disabled>\n <Input label=\"Name\" placeholder=\"Your name\" />\n <Input label=\"Email\" type=\"email\" placeholder=\"Your email\" />\n</fieldset>"
115
119
  },
116
120
  {
117
- "title": "Context-Aware Rendering",
121
+ "title": "Context-Aware Rendering › Default (with label)",
118
122
  "code": "<Input label=\"Username\" placeholder=\"Enter username\" />"
119
123
  },
120
124
  {
121
- "title": "Context-Aware Rendering",
125
+ "title": "Context-Aware Rendering › With Field Wrapper",
122
126
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Username\"\n labelProps={{ htmlFor: 'username-field' }}\n >\n <Field.Body>\n <Field>\n <Input id=\"username-field\" placeholder=\"Enter username\" />\n </Field>\n </Field.Body>\n </Field>\n );\n}"
123
127
  },
124
128
  {
125
- "title": "Context-Aware Rendering",
129
+ "title": "Context-Aware Rendering › With Field and Control Wrappers",
126
130
  "code": "function example() {\n return (\n <Field\n horizontal\n label=\"Username\"\n labelProps={{ htmlFor: 'username-field-control' }}\n >\n <Field.Body>\n <Field>\n <Control iconLeftName=\"user\">\n <Input id=\"username-field-control\" placeholder=\"Enter username\" />\n </Control>\n </Field>\n </Field.Body>\n </Field>\n );\n}"
127
131
  }
128
132
  ],
@@ -22,19 +22,19 @@
22
22
  "code": "<>\n <Message title=\"Default Size\">This is the default size message.</Message>\n <Message size=\"small\" title=\"Small\">\n This is a small message.\n </Message>\n <Message size=\"medium\" title=\"Medium\">\n This is a medium message.\n </Message>\n <Message size=\"large\" title=\"Large\">\n This is a large message.\n </Message>\n</>"
23
23
  },
24
24
  {
25
- "title": "Compound (dot-notation) usage",
25
+ "title": "Compound (dot-notation) usage › Complete Message with Compound Components",
26
26
  "code": "<Message color=\"info\">\n <Message.Header>\n <Paragraph>Compound Component Message</Paragraph>\n <Delete aria-label=\"delete\" />\n </Message.Header>\n <Message.Body>\n <Paragraph>\n This message is built using compound components for maximum flexibility\n and control over each section.\n </Paragraph>\n <Paragraph>\n You can include multiple paragraphs and elements in the body.\n </Paragraph>\n </Message.Body>\n</Message>"
27
27
  },
28
28
  {
29
- "title": "Compound (dot-notation) usage",
29
+ "title": "Compound (dot-notation) usage › Minimal Message with Body Only",
30
30
  "code": "<Message color=\"success\">\n <Message.Body>\n <Paragraph>\n A simple message using only the Message.Body compound component.\n </Paragraph>\n </Message.Body>\n</Message>"
31
31
  },
32
32
  {
33
- "title": "Compound (dot-notation) usage",
33
+ "title": "Compound (dot-notation) usage › Header-Only Message",
34
34
  "code": "<Message color=\"warning\">\n <Message.Header>\n <Paragraph>Header-only message</Paragraph>\n <Delete aria-label=\"delete\" />\n </Message.Header>\n</Message>"
35
35
  },
36
36
  {
37
- "title": "Compound (dot-notation) usage",
37
+ "title": "Compound (dot-notation) usage › Mixed Approach",
38
38
  "code": "<Message color=\"danger\" title=\"Mixed Approach\">\n <Message.Body>\n <Paragraph>\n You can mix prop-based and compound component approaches!\n </Paragraph>\n <Paragraph>\n This message uses the title prop but compound components for the body.\n </Paragraph>\n </Message.Body>\n</Message>"
39
39
  }
40
40
  ],