@plastic-js/tsumiki 0.1.22 → 0.1.24

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 (199) hide show
  1. package/README.md +838 -65
  2. package/dist/components/Accordion.js +93 -4
  3. package/dist/components/Avatar.js +96 -4
  4. package/dist/components/BottomSheet.js +131 -0
  5. package/dist/components/Button.js +194 -0
  6. package/dist/components/CardNumberInput.js +28 -44
  7. package/dist/components/Carousel.js +71 -5
  8. package/dist/components/Checkbox.js +178 -4
  9. package/dist/components/Clipboard.js +135 -5
  10. package/dist/components/CloseButton.js +97 -0
  11. package/dist/components/Collapsible.js +22 -4
  12. package/dist/components/ColorPicker.js +327 -4
  13. package/dist/components/Combobox.js +86 -13
  14. package/dist/components/ConfirmDialog.js +174 -19
  15. package/dist/components/DateInput.js +437 -5
  16. package/dist/components/{DatePickerMobile/wheel.js → DateWheel.js} +1 -3
  17. package/dist/components/Dialog.js +214 -110
  18. package/dist/components/Drawer.js +169 -4
  19. package/dist/components/Field.js +121 -5
  20. package/dist/components/Fieldset.js +64 -5
  21. package/dist/components/FileUpload.js +181 -4
  22. package/dist/components/FocusTrap.js +0 -2
  23. package/dist/components/Icon.js +32 -17
  24. package/dist/components/Input.js +211 -0
  25. package/dist/components/Listbox.js +47 -4
  26. package/dist/components/Menu.js +99 -4
  27. package/dist/components/MoneyInput.js +33 -85
  28. package/dist/components/NumberInput.js +117 -4
  29. package/dist/components/Pagination.js +91 -5
  30. package/dist/components/Popover.js +123 -4
  31. package/dist/components/Portal.js +0 -2
  32. package/dist/components/Presence.js +0 -2
  33. package/dist/components/Progress.js +107 -4
  34. package/dist/components/RadioGroup.js +104 -4
  35. package/dist/components/RatingGroup.js +75 -4
  36. package/dist/components/SearchInput.js +60 -55
  37. package/dist/components/Select.js +428 -5
  38. package/dist/components/SelectPc.js +239 -0
  39. package/dist/components/SignaturePad.js +77 -4
  40. package/dist/components/Skeleton.js +2 -4
  41. package/dist/components/Slider.js +112 -4
  42. package/dist/components/Spinner.js +41 -0
  43. package/dist/components/Splitter.js +51 -4
  44. package/dist/components/Steps.js +259 -4
  45. package/dist/components/SwipeReveal.js +2 -4
  46. package/dist/components/Switch.js +147 -4
  47. package/dist/components/Tabs.js +80 -4
  48. package/dist/components/TagsInput.js +128 -4
  49. package/dist/components/Toast.js +174 -4
  50. package/dist/components/Toggle.js +39 -4
  51. package/dist/components/ToggleGroup.js +103 -4
  52. package/dist/components/Tour.js +63 -4
  53. package/dist/components/TreeView.js +113 -4
  54. package/dist/index.js +44 -45
  55. package/dist/tsumiki.css +1 -0
  56. package/docs/api.md +670 -0
  57. package/docs/component-api-pattern.md +362 -0
  58. package/package.json +16 -6
  59. package/src/styles/color.css +112 -0
  60. package/src/styles/index.css +1 -0
  61. package/src/styles/radius.css +27 -0
  62. package/src/styles/reset.css +111 -0
  63. package/src/styles/shadow.css +5 -0
  64. package/src/styles/sizing.css +59 -0
  65. package/src/styles/spacing.css +9 -0
  66. package/src/styles/theme.css +38 -0
  67. package/src/styles/tokens.css +22 -0
  68. package/src/styles/transition.css +5 -0
  69. package/src/styles/typography.css +8 -0
  70. package/dist/components/Accordion.js.map +0 -1
  71. package/dist/components/Avatar.js.map +0 -1
  72. package/dist/components/CardNumberInput.js.map +0 -1
  73. package/dist/components/Carousel.js.map +0 -1
  74. package/dist/components/Checkbox.js.map +0 -1
  75. package/dist/components/Clipboard.js.map +0 -1
  76. package/dist/components/Collapsible.js.map +0 -1
  77. package/dist/components/ColorPicker.js.map +0 -1
  78. package/dist/components/Combobox.js.map +0 -1
  79. package/dist/components/ConfirmDialog.js.map +0 -1
  80. package/dist/components/DateInput.js.map +0 -1
  81. package/dist/components/DatePicker.js +0 -7
  82. package/dist/components/DatePicker.js.map +0 -1
  83. package/dist/components/DatePickerMobile/index.js +0 -479
  84. package/dist/components/DatePickerMobile/index.js.map +0 -1
  85. package/dist/components/DatePickerMobile/wheel.js.map +0 -1
  86. package/dist/components/Dialog.js.map +0 -1
  87. package/dist/components/Drawer.js.map +0 -1
  88. package/dist/components/Field.js.map +0 -1
  89. package/dist/components/Fieldset.js.map +0 -1
  90. package/dist/components/FileUpload.js.map +0 -1
  91. package/dist/components/FilterableSelect.js +0 -210
  92. package/dist/components/FilterableSelect.js.map +0 -1
  93. package/dist/components/FilterableSelectMobile.js +0 -167
  94. package/dist/components/FilterableSelectMobile.js.map +0 -1
  95. package/dist/components/FocusTrap.js.map +0 -1
  96. package/dist/components/HoverCard.js +0 -7
  97. package/dist/components/HoverCard.js.map +0 -1
  98. package/dist/components/Icon.js.map +0 -1
  99. package/dist/components/Listbox.js.map +0 -1
  100. package/dist/components/Menu.js.map +0 -1
  101. package/dist/components/MoneyInput.js.map +0 -1
  102. package/dist/components/NumberInput.js.map +0 -1
  103. package/dist/components/Pagination.js.map +0 -1
  104. package/dist/components/Popover.js.map +0 -1
  105. package/dist/components/Portal.js.map +0 -1
  106. package/dist/components/Presence.js.map +0 -1
  107. package/dist/components/Progress.js.map +0 -1
  108. package/dist/components/RadioGroup.js.map +0 -1
  109. package/dist/components/RatingGroup.js.map +0 -1
  110. package/dist/components/SearchInput.js.map +0 -1
  111. package/dist/components/Select.js.map +0 -1
  112. package/dist/components/SelectMobile/anatomy.js +0 -10
  113. package/dist/components/SelectMobile/anatomy.js.map +0 -1
  114. package/dist/components/SelectMobile/index.js +0 -310
  115. package/dist/components/SelectMobile/index.js.map +0 -1
  116. package/dist/components/SignaturePad.js.map +0 -1
  117. package/dist/components/Skeleton.js.map +0 -1
  118. package/dist/components/Slider.js.map +0 -1
  119. package/dist/components/Splitter.js.map +0 -1
  120. package/dist/components/Steps.js.map +0 -1
  121. package/dist/components/SwipeReveal.js.map +0 -1
  122. package/dist/components/Switch.js.map +0 -1
  123. package/dist/components/Tabs.js.map +0 -1
  124. package/dist/components/TagsInput.js.map +0 -1
  125. package/dist/components/Toast.js.map +0 -1
  126. package/dist/components/Toggle.js.map +0 -1
  127. package/dist/components/ToggleGroup.js.map +0 -1
  128. package/dist/components/Tooltip.js +0 -7
  129. package/dist/components/Tooltip.js.map +0 -1
  130. package/dist/components/Tour.js.map +0 -1
  131. package/dist/components/TreeView.js.map +0 -1
  132. package/dist/node_modules/framesync/dist/es/create-render-step.js +0 -54
  133. package/dist/node_modules/framesync/dist/es/create-render-step.js.map +0 -1
  134. package/dist/node_modules/framesync/dist/es/index.js +0 -61
  135. package/dist/node_modules/framesync/dist/es/index.js.map +0 -1
  136. package/dist/node_modules/framesync/dist/es/on-next-frame.js +0 -8
  137. package/dist/node_modules/framesync/dist/es/on-next-frame.js.map +0 -1
  138. package/dist/node_modules/hey-listen/dist/hey-listen.es.js +0 -15
  139. package/dist/node_modules/hey-listen/dist/hey-listen.es.js.map +0 -1
  140. package/dist/node_modules/popmotion/dist/es/animations/generators/decay.js +0 -24
  141. package/dist/node_modules/popmotion/dist/es/animations/generators/decay.js.map +0 -1
  142. package/dist/node_modules/popmotion/dist/es/animations/generators/keyframes.js +0 -40
  143. package/dist/node_modules/popmotion/dist/es/animations/generators/keyframes.js.map +0 -1
  144. package/dist/node_modules/popmotion/dist/es/animations/generators/spring.js +0 -96
  145. package/dist/node_modules/popmotion/dist/es/animations/generators/spring.js.map +0 -1
  146. package/dist/node_modules/popmotion/dist/es/animations/index.js +0 -94
  147. package/dist/node_modules/popmotion/dist/es/animations/index.js.map +0 -1
  148. package/dist/node_modules/popmotion/dist/es/animations/inertia.js +0 -74
  149. package/dist/node_modules/popmotion/dist/es/animations/inertia.js.map +0 -1
  150. package/dist/node_modules/popmotion/dist/es/animations/utils/detect-animation-from-options.js +0 -21
  151. package/dist/node_modules/popmotion/dist/es/animations/utils/detect-animation-from-options.js.map +0 -1
  152. package/dist/node_modules/popmotion/dist/es/animations/utils/elapsed.js +0 -14
  153. package/dist/node_modules/popmotion/dist/es/animations/utils/elapsed.js.map +0 -1
  154. package/dist/node_modules/popmotion/dist/es/animations/utils/find-spring.js +0 -68
  155. package/dist/node_modules/popmotion/dist/es/animations/utils/find-spring.js.map +0 -1
  156. package/dist/node_modules/popmotion/dist/es/easing/index.js +0 -28
  157. package/dist/node_modules/popmotion/dist/es/easing/index.js.map +0 -1
  158. package/dist/node_modules/popmotion/dist/es/easing/utils.js +0 -13
  159. package/dist/node_modules/popmotion/dist/es/easing/utils.js.map +0 -1
  160. package/dist/node_modules/popmotion/dist/es/utils/clamp.js +0 -6
  161. package/dist/node_modules/popmotion/dist/es/utils/clamp.js.map +0 -1
  162. package/dist/node_modules/popmotion/dist/es/utils/hsla-to-rgba.js +0 -35
  163. package/dist/node_modules/popmotion/dist/es/utils/hsla-to-rgba.js.map +0 -1
  164. package/dist/node_modules/popmotion/dist/es/utils/inc.js +0 -6
  165. package/dist/node_modules/popmotion/dist/es/utils/inc.js.map +0 -1
  166. package/dist/node_modules/popmotion/dist/es/utils/interpolate.js +0 -69
  167. package/dist/node_modules/popmotion/dist/es/utils/interpolate.js.map +0 -1
  168. package/dist/node_modules/popmotion/dist/es/utils/mix-color.js +0 -45
  169. package/dist/node_modules/popmotion/dist/es/utils/mix-color.js.map +0 -1
  170. package/dist/node_modules/popmotion/dist/es/utils/mix-complex.js +0 -61
  171. package/dist/node_modules/popmotion/dist/es/utils/mix-complex.js.map +0 -1
  172. package/dist/node_modules/popmotion/dist/es/utils/mix.js +0 -6
  173. package/dist/node_modules/popmotion/dist/es/utils/mix.js.map +0 -1
  174. package/dist/node_modules/popmotion/dist/es/utils/pipe.js +0 -7
  175. package/dist/node_modules/popmotion/dist/es/utils/pipe.js.map +0 -1
  176. package/dist/node_modules/popmotion/dist/es/utils/progress.js +0 -9
  177. package/dist/node_modules/popmotion/dist/es/utils/progress.js.map +0 -1
  178. package/dist/node_modules/popmotion/dist/es/utils/velocity-per-second.js +0 -8
  179. package/dist/node_modules/popmotion/dist/es/utils/velocity-per-second.js.map +0 -1
  180. package/dist/node_modules/popmotion/node_modules/tslib/tslib.es6.js +0 -13
  181. package/dist/node_modules/popmotion/node_modules/tslib/tslib.es6.js.map +0 -1
  182. package/dist/node_modules/style-value-types/dist/es/color/hex.js +0 -39
  183. package/dist/node_modules/style-value-types/dist/es/color/hex.js.map +0 -1
  184. package/dist/node_modules/style-value-types/dist/es/color/hsla.js +0 -16
  185. package/dist/node_modules/style-value-types/dist/es/color/hsla.js.map +0 -1
  186. package/dist/node_modules/style-value-types/dist/es/color/index.js +0 -20
  187. package/dist/node_modules/style-value-types/dist/es/color/index.js.map +0 -1
  188. package/dist/node_modules/style-value-types/dist/es/color/rgba.js +0 -15
  189. package/dist/node_modules/style-value-types/dist/es/color/rgba.js.map +0 -1
  190. package/dist/node_modules/style-value-types/dist/es/color/utils.js +0 -19
  191. package/dist/node_modules/style-value-types/dist/es/color/utils.js.map +0 -1
  192. package/dist/node_modules/style-value-types/dist/es/complex/index.js +0 -58
  193. package/dist/node_modules/style-value-types/dist/es/complex/index.js.map +0 -1
  194. package/dist/node_modules/style-value-types/dist/es/numbers/index.js +0 -13
  195. package/dist/node_modules/style-value-types/dist/es/numbers/index.js.map +0 -1
  196. package/dist/node_modules/style-value-types/dist/es/numbers/units.js +0 -16
  197. package/dist/node_modules/style-value-types/dist/es/numbers/units.js.map +0 -1
  198. package/dist/node_modules/style-value-types/dist/es/utils.js +0 -13
  199. package/dist/node_modules/style-value-types/dist/es/utils.js.map +0 -1
@@ -0,0 +1,362 @@
1
+ # Tsumiki Component Guide
2
+
3
+ A single reference for `@plastic-js/tsumiki` covering the component inventory & status (Classification) and the canonical component API pattern (API Pattern).
4
+
5
+ ---
6
+
7
+ ## Part 1 — Component Classification
8
+
9
+ All 51 components are classified along two orthogonal axes.
10
+
11
+ ### Axis 1: Development Lifecycle
12
+
13
+ Whether the component is ready for production use or still under active development.
14
+
15
+ | Stage | Definition |
16
+ |-------|------------|
17
+ | **Completed** | Production-ready; API stable. |
18
+ | **In Development** | Still being built; API may change. |
19
+
20
+ ### Axis 2: Architectural Foundation
21
+
22
+ Whether the component is built on top of a same-named Ark primitive, or implemented independently.
23
+
24
+ | Foundation | Definition |
25
+ |------------|------------|
26
+ | **Ark-Backed** | Directly wraps a corresponding `@plastic-js/ark` primitive of the same name. |
27
+ | **Custom-Built** | Uses no Ark primitive; implemented with `@plastic-js/plastic`, `@emotion/css`, or the Web platform directly. |
28
+
29
+ ### Component Matrix
30
+
31
+ #### Completed · Ark-Backed (30)
32
+
33
+ | Component | Ark Primitive |
34
+ |-----------|---------------|
35
+ | Avatar | `ArkAvatar` |
36
+ | Button | `ark("button")` via factory |
37
+ | Checkbox | `ArkCheckbox` |
38
+ | Collapsible | `ArkCollapsible` |
39
+ | ColorPicker | `ArkColorPicker` |
40
+ | Dialog | `ArkDialog` |
41
+ | Drawer | `ArkDrawer` |
42
+ | FileUpload | `ArkFileUpload` |
43
+ | FocusTrap | `ArkFocusTrap` |
44
+ | Input | `ark("input")` via factory |
45
+ | Menu | `ArkMenu` |
46
+ | NumberInput | `ArkNumberInput` |
47
+ | Pagination | `ArkPagination` |
48
+ | Popover | `ArkPopover` |
49
+ | Portal | `ArkPortal` |
50
+ | Presence | `ArkPresence` |
51
+ | Progress | `ArkProgress` |
52
+ | RadioGroup | `ArkRadioGroup` |
53
+ | RatingGroup | `ArkRatingGroup` |
54
+ | SelectPc | `ArkSelect` |
55
+ | SignaturePad | `ArkSignaturePad` |
56
+ | Slider | `ArkSlider` |
57
+ | Splitter | `ArkSplitter` |
58
+ | Steps | `ArkSteps` |
59
+ | Switch | `ArkSwitch` |
60
+ | Tabs | `ArkTabs` |
61
+ | TagsInput | `ArkTagsInput` |
62
+ | Toast | `ArkToast` |
63
+ | Toggle | `ArkToggle` |
64
+ | ToggleGroup | `ArkToggleGroup` |
65
+
66
+ #### Completed · Custom-Built (15)
67
+
68
+ | Component | Built With |
69
+ |-----------|------------|
70
+ | BottomSheet | `@plastic-js/plastic` + `Portal` |
71
+ | CardNumberInput | Composes `Input` |
72
+ | Clipboard | Web Clipboard API |
73
+ | CloseButton | `@emotion/css` |
74
+ | ConfirmDialog | Composes `Dialog` |
75
+ | DateInput | `DateWheel` utility |
76
+ | Field | `@emotion/css` |
77
+ | Fieldset | `@emotion/css` |
78
+ | Icon | `@emotion/css` |
79
+ | MoneyInput | Composes `Input` |
80
+ | SearchInput | Composes `Input` |
81
+ | Select | Custom state machine with `Loop` |
82
+ | Skeleton | Pure CSS |
83
+ | Spinner | Pure CSS |
84
+ | SwipeReveal | Touch event gestures |
85
+
86
+ #### In Development · Ark-Backed (6)
87
+
88
+ | Component | Ark Primitive |
89
+ |-----------|---------------|
90
+ | Accordion | `ArkAccordion` |
91
+ | Carousel | `ArkCarousel` |
92
+ | Combobox | `ArkCombobox` |
93
+ | Listbox | `ArkListbox` |
94
+ | Tour | `ArkTour` |
95
+ | TreeView | `ArkTreeView` |
96
+
97
+ #### In Development · Custom-Built (0)
98
+
99
+ *No components currently in this quadrant.*
100
+
101
+ ### Summary
102
+
103
+ ```
104
+ Ark-Backed Custom-Built
105
+ ┌─────────────────┬─────────────────┐
106
+ Completed │ 30 │ 15 │ 45
107
+ ├─────────────────┼─────────────────┤
108
+ In Development │ 6 │ 0 │ 6
109
+ └─────────────────┴─────────────────┘
110
+ 36 15 51
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Part 2 — Component API Pattern
116
+
117
+ This section defines the canonical component API pattern for `@plastic-js/tsumiki`.
118
+
119
+ ### Design Goals
120
+
121
+ 1. **Simplify Ark APIs** — tsumiki wraps `@plastic-js/ark` components with theme styling, default props, and opinionated presets
122
+ 2. **Unified consumer experience** — all components follow the same access pattern
123
+ 3. **Escape hatch** — consumers can always reach the raw Ark component when needed
124
+ 4. **Controlled-only** — all tsumiki components are controlled; uncontrolled mode (`defaultValue`, `defaultOpen`, `defaultChecked`, etc.) is NOT supported even if the underlying Ark component supports it
125
+
126
+ ### Core Rules
127
+
128
+ #### Rule 0: Controlled-Only — No Uncontrolled Mode
129
+
130
+ Tsumiki does not support uncontrolled mode. Every component that manages state (`value`, `open`, `checked`, etc.) must receive it as a controlled signal prop and report changes via a callback. No `defaultValue`, `defaultOpen`, `defaultChecked`, or similar props exist on tsumiki components.
131
+
132
+ ```jsx
133
+ // CORRECT: Controlled — consumer owns the state signal
134
+ const isOpen = createSignal(false)
135
+ <Dialog open={isOpen} onOpenChange={v => isOpen(v.open)} />
136
+
137
+ // WRONG: Uncontrolled (not supported)
138
+ <Dialog defaultOpen />
139
+ ```
140
+
141
+ If a consumer wants an initial value, they set it in their own `createSignal()` call. No tsumiki component creates internal state for uncontrolled usage.
142
+
143
+ **Rationale:**
144
+ - State ownership is explicit and predictable
145
+ - Components are easier to test and debug
146
+ - The entire API follows a uniform `value`/`onValueChange` contract
147
+ - While Ark primitives may technically accept `default*` props internally, consumers must not rely on this — tsumiki reserves the right to break uncontrolled usage
148
+
149
+ #### Rule 1: The default export IS the render component
150
+
151
+ ```jsx
152
+ import { Comp as ArkComp } from '@plastic-js/ark'
153
+
154
+ const Comp = (props = {}) => (
155
+ <ArkComp.Root className={styles} {...rest}>
156
+ {/* tsumiki theme styling */}
157
+ </ArkComp.Root>
158
+ )
159
+
160
+ export default Comp
161
+ ```
162
+
163
+ The default export is always a **renderable component**. It wraps Ark's root with:
164
+ - CSS-in-JS via `@emotion/css`
165
+ - `var(--tsu-*)` design tokens
166
+ - `splitProps` / `mergeProps` for prop defaults
167
+ - Simplified, opinionated default behavior
168
+
169
+ #### Rule 2: `.origin` maps to raw Ark components
170
+
171
+ ```js
172
+ Comp.origin = {
173
+ Root: ArkComp.Root,
174
+ Label: ArkComp.Label,
175
+ Control: ArkComp.Control,
176
+ }
177
+ ```
178
+
179
+ - **`.origin`** (lowercase) is the **only** static property on the component
180
+ - It maps tsumiki-friendly names to their raw `@plastic-js/ark` counterparts
181
+ - Only mount what exists on the Ark component — if Ark has no `Label` sub-part, don't add it
182
+ - The `origin` object serves as the **escape hatch** for consumers who need direct access to Ark's full API
183
+
184
+ #### Rule 3: No other static properties
185
+
186
+ ```js
187
+ // ❌ WRONG — do not attach sub-components as direct properties
188
+ Comp.Root = Comp
189
+ Comp.Trigger = SomeTrigger
190
+ Comp.Content = SomeContent
191
+
192
+ // ❌ WRONG — do not use Object.assign to spread sub-components
193
+ const Comp = Object.assign(CompRoot, { Root: CompRoot, Trigger, Content })
194
+
195
+ // ✅ CORRECT — only .origin
196
+ Comp.origin = { Root: ArkComp.Root, Trigger: ArkComp.Trigger, Content: ArkComp.Content }
197
+ ```
198
+
199
+ The component function itself carries **nothing** except `.origin`.
200
+
201
+ #### Rule 4: Components without an Ark counterpart have no `.origin`
202
+
203
+ ```js
204
+ // Fully custom component (no Ark import at all)
205
+ import { css } from '@emotion/css'
206
+
207
+ const Spinner = (props = {}) => <div>...</div>
208
+
209
+ // No .origin — there is no Ark counterpart
210
+ export default Spinner
211
+ ```
212
+
213
+ #### Rule 5: Sub-components (when needed) are named exports
214
+
215
+ For components that have meaningful, tsumiki-wrapped sub-components (see [Multi-Part Component Pattern](#multi-part-component-pattern)), sub-components are exported as **named exports** from the module, NOT attached to the default export.
216
+
217
+ #### Rule 6: Dual export (default + named)
218
+
219
+ Every component module **must** export both a default and a named export for the top-level component:
220
+
221
+ ```js
222
+ export default Comp
223
+ export { Comp }
224
+ ```
225
+
226
+ This ensures consumers can import using either style:
227
+
228
+ ```js
229
+ import Comp from '@plastic-js/tsumiki/components/Comp.jsx'
230
+ import { Comp } from '@plastic-js/tsumiki/components/Comp.jsx'
231
+ ```
232
+
233
+ When the internal variable name differs from the component name, use an alias:
234
+
235
+ ```js
236
+ export default Root
237
+ export { Root as FileUpload }
238
+ ```
239
+
240
+ ### Naming Conventions
241
+
242
+ | Element | Convention | Example |
243
+ |---------|-----------|---------|
244
+ | Ark import alias | `Ark` + PascalCase name | `import { Dialog as ArkDialog }` |
245
+ | Component function | PascalCase, same as default export name | `const Dialog = (props) => ...` |
246
+ | origin keys | PascalCase, matching Ark sub-part names | `{ Root, Trigger, Content }` |
247
+ | `.origin` property | lowercase `origin` | `Dialog.origin = { ... }` |
248
+ | CSS class variables | `camelCase` + `Class` suffix | `rootClass`, `contentClass` |
249
+
250
+ ### Consumer Usage
251
+
252
+ #### Simple component (single wrapper)
253
+
254
+ ```jsx
255
+ import { Button } from '@plastic-js/tsumiki'
256
+
257
+ // Primary usage: tsumiki-styled
258
+ <Button solid>Click me</Button>
259
+
260
+ // Escape hatch: raw Ark API
261
+ <Button.origin.Root>...</Button.origin.Root>
262
+ ```
263
+
264
+ #### Simple component wrapping multiple Ark sub-parts
265
+
266
+ ```jsx
267
+ import { Checkbox } from '@plastic-js/tsumiki'
268
+
269
+ // Primary usage: tsumiki-styled (wraps Root + Control + Indicator + Label + HiddenInput)
270
+ <Checkbox>Accept terms</Checkbox>
271
+
272
+ // Escape hatch: individual raw Ark sub-parts
273
+ <Checkbox.origin.Root>
274
+ <Checkbox.origin.Control>
275
+ <Checkbox.origin.Indicator />
276
+ </Checkbox.origin.Control>
277
+ </Checkbox.origin.Root>
278
+ ```
279
+
280
+ #### Multi-part component (see below)
281
+
282
+ ```jsx
283
+ import Menu, { MenuTrigger, MenuContent, MenuItem } from '@plastic-js/tsumiki'
284
+
285
+ <Menu>
286
+ <MenuTrigger>Open</MenuTrigger>
287
+ <MenuContent>
288
+ <MenuItem>Action</MenuItem>
289
+ </MenuContent>
290
+ </Menu>
291
+
292
+ // Escape hatch
293
+ <Menu.origin.Root>
294
+ <Menu.origin.Trigger>...</Menu.origin.Trigger>
295
+ <Menu.origin.Content>...</Menu.origin.Content>
296
+ </Menu.origin.Root>
297
+ ```
298
+
299
+ ### Multi-Part Component Pattern
300
+
301
+ For components that have meaningful tsumiki-wrapped sub-components (e.g., Menu, Dialog, Accordion), each sub-component is a named export:
302
+
303
+ ```jsx
304
+ import { Menu as ArkMenu } from '@plastic-js/ark'
305
+
306
+ // Default export: the root wrapper
307
+ const Menu = (props = {}) => (
308
+ <ArkMenu.Root className={rootClass} {...rest}>
309
+ {children}
310
+ </ArkMenu.Root>
311
+ )
312
+
313
+ // Named exports: tsumiki-wrapped sub-components
314
+ export const MenuTrigger = (props = {}) => (
315
+ <ArkMenu.Trigger className={triggerClass} {...rest}>
316
+ {children}
317
+ </ArkMenu.Trigger>
318
+ )
319
+
320
+ export const MenuContent = (props = {}) => (
321
+ <ArkMenu.Content className={contentClass} {...rest}>
322
+ {children}
323
+ </ArkMenu.Content>
324
+ )
325
+
326
+ Menu.origin = {
327
+ Root: ArkMenu.Root,
328
+ Trigger: ArkMenu.Trigger,
329
+ Content: ArkMenu.Content,
330
+ }
331
+
332
+ export default Menu
333
+ ```
334
+
335
+ #### Barrel exports for multi-part components
336
+
337
+ In `src/index.js`, both default and named exports are re-exported:
338
+
339
+ ```js
340
+ export {
341
+ default as Menu,
342
+ MenuTrigger,
343
+ MenuContent,
344
+ MenuItem,
345
+ MenuSeparator,
346
+ } from './components/Menu.jsx'
347
+ ```
348
+
349
+ ### File Structure
350
+
351
+ ```
352
+ src/components/Comp.jsx
353
+ ├── imports (@emotion/css, @plastic-js/ark, @plastic-js/plastic)
354
+ ├── CSS class definitions (rootClass, triggerClass, etc.)
355
+ ├── Component function (default export)
356
+ ├── [Named exports for sub-components, if multi-part]
357
+ ├── .origin assignment
358
+ ├── export default Comp
359
+ └── export { Comp }
360
+ ```
361
+
362
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plastic-js/tsumiki",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "A UI component library for Plastic JS.",
5
5
  "license": "MIT",
6
6
  "author": "tigre",
@@ -27,10 +27,15 @@
27
27
  ".": {
28
28
  "import": "./dist/index.js",
29
29
  "default": "./dist/index.js"
30
- }
30
+ },
31
+ "./styles": "./dist/tsumiki.css",
32
+ "./tsumiki.css": "./dist/tsumiki.css",
33
+ "./styles/*": "./src/styles/*"
31
34
  },
32
35
  "files": [
33
36
  "dist",
37
+ "src/styles",
38
+ "docs",
34
39
  "LICENSE",
35
40
  "README.md"
36
41
  ],
@@ -40,23 +45,28 @@
40
45
  },
41
46
  "scripts": {
42
47
  "dev": "vite",
43
- "build": "vite build",
48
+ "build": "vite build && npm run build:styles",
49
+ "build:styles": "vite build --config vite.styles.config.js && cp dist-styles/*.css dist/tsumiki.css && rm -rf dist-styles",
44
50
  "prepublishOnly": "npm run build",
45
51
  "preview": "vite preview",
52
+ "theme": "node scripts/theme.js",
46
53
  "e2e:repro": "node e2e/dlgcbx-repro.mjs"
47
54
  },
48
55
  "dependencies": {
49
56
  "@emotion/css": "^11.13.5",
50
- "@plastic-js/ark": "^1.0.12",
51
- "@plastic-js/plastic": "^1.0.22",
57
+ "@zag-js/select": "1.40.0",
52
58
  "popmotion": "^11.0.5"
53
59
  },
54
60
  "peerDependencies": {
55
- "@zag-js/combobox": "1.40.0"
61
+ "@plastic-js/ark": "^1.0.16",
62
+ "@plastic-js/plastic": "^1.0.22"
56
63
  },
57
64
  "devDependencies": {
58
65
  "@babel/core": "^7.29.7",
66
+ "@plastic-js/ark": "^1.0.16",
59
67
  "@plastic-js/babel-preset-plastic": "^0.1.11",
68
+ "@plastic-js/plastic": "^1.0.22",
69
+ "@radix-ui/colors": "^3.0.0",
60
70
  "@zag-js/combobox": "1.40.0",
61
71
  "puppeteer-core": "^25.1.0",
62
72
  "vite": "^8.0.15"
@@ -0,0 +1,112 @@
1
+ @import './theme.css';
2
+ @import '@radix-ui/colors/red.css';
3
+ @import '@radix-ui/colors/red-alpha.css';
4
+ @import '@radix-ui/colors/red-dark.css';
5
+ @import '@radix-ui/colors/red-dark-alpha.css';
6
+ @import '@radix-ui/colors/green.css';
7
+ @import '@radix-ui/colors/green-alpha.css';
8
+ @import '@radix-ui/colors/green-dark.css';
9
+ @import '@radix-ui/colors/green-dark-alpha.css';
10
+ @import '@radix-ui/colors/amber.css';
11
+ @import '@radix-ui/colors/amber-alpha.css';
12
+ @import '@radix-ui/colors/amber-dark.css';
13
+ @import '@radix-ui/colors/amber-dark-alpha.css';
14
+
15
+ :root {
16
+ --tsu-bg: var(--tsu-neutral-1);
17
+ --tsu-fg: var(--tsu-neutral-12);
18
+
19
+ /* Info (accent) — full 12-step palette */
20
+ --tsu-info-1: var(--tsu-accent-1);
21
+ --tsu-info-2: var(--tsu-accent-2);
22
+ --tsu-info-3: var(--tsu-accent-3);
23
+ --tsu-info-4: var(--tsu-accent-4);
24
+ --tsu-info-5: var(--tsu-accent-5);
25
+ --tsu-info-6: var(--tsu-accent-6);
26
+ --tsu-info-7: var(--tsu-accent-7);
27
+ --tsu-info-8: var(--tsu-accent-8);
28
+ --tsu-info-9: var(--tsu-accent-9);
29
+ --tsu-info-10: var(--tsu-accent-10);
30
+ --tsu-info-11: var(--tsu-accent-11);
31
+ --tsu-info-12: var(--tsu-accent-12);
32
+
33
+ /* Danger (red) */
34
+ --tsu-danger-1: var(--red-1);
35
+ --tsu-danger-2: var(--red-2);
36
+ --tsu-danger-3: var(--red-3);
37
+ --tsu-danger-4: var(--red-4);
38
+ --tsu-danger-5: var(--red-5);
39
+ --tsu-danger-6: var(--red-6);
40
+ --tsu-danger-7: var(--red-7);
41
+ --tsu-danger-8: var(--red-8);
42
+ --tsu-danger-9: var(--red-9);
43
+ --tsu-danger-10: var(--red-10);
44
+ --tsu-danger-11: var(--red-11);
45
+ --tsu-danger-12: var(--red-12);
46
+
47
+ /* Success (green) */
48
+ --tsu-success-1: var(--green-1);
49
+ --tsu-success-2: var(--green-2);
50
+ --tsu-success-3: var(--green-3);
51
+ --tsu-success-4: var(--green-4);
52
+ --tsu-success-5: var(--green-5);
53
+ --tsu-success-6: var(--green-6);
54
+ --tsu-success-7: var(--green-7);
55
+ --tsu-success-8: var(--green-8);
56
+ --tsu-success-9: var(--green-9);
57
+ --tsu-success-10: var(--green-10);
58
+ --tsu-success-11: var(--green-11);
59
+ --tsu-success-12: var(--green-12);
60
+
61
+ /* Warning (amber) */
62
+ --tsu-warning-1: var(--amber-1);
63
+ --tsu-warning-2: var(--amber-2);
64
+ --tsu-warning-3: var(--amber-3);
65
+ --tsu-warning-4: var(--amber-4);
66
+ --tsu-warning-5: var(--amber-5);
67
+ --tsu-warning-6: var(--amber-6);
68
+ --tsu-warning-7: var(--amber-7);
69
+ --tsu-warning-8: var(--amber-8);
70
+ --tsu-warning-9: var(--amber-9);
71
+ --tsu-warning-10: var(--amber-10);
72
+ --tsu-warning-11: var(--amber-11);
73
+ --tsu-warning-12: var(--amber-12);
74
+
75
+ /* Neutral Alpha Overlay (used for shadows/elevation) */
76
+ --tsu-neutral-alpha-1: var(--olive-a1);
77
+ --tsu-neutral-alpha-2: var(--olive-a2);
78
+ --tsu-neutral-alpha-3: var(--olive-a3);
79
+ --tsu-neutral-alpha-4: var(--olive-a4);
80
+ --tsu-neutral-alpha-5: var(--olive-a5);
81
+ --tsu-neutral-alpha-6: var(--olive-a6);
82
+ --tsu-neutral-alpha-7: var(--olive-a7);
83
+ --tsu-neutral-alpha-8: var(--olive-a8);
84
+ --tsu-neutral-alpha-9: var(--olive-a9);
85
+ --tsu-neutral-alpha-10: var(--olive-a10);
86
+ --tsu-neutral-alpha-11: var(--olive-a11);
87
+ --tsu-neutral-alpha-12: var(--olive-a12);
88
+
89
+ /* Disabled State */
90
+ --tsu-disabled-bg: var(--tsu-neutral-3);
91
+ --tsu-disabled-fg: var(--tsu-neutral-9);
92
+ --tsu-disabled-border: var(--tsu-neutral-7);
93
+
94
+ /* Focus State */
95
+ --tsu-focus-bg: var(--tsu-neutral-2);
96
+ --tsu-focus-border: var(--tsu-accent-8);
97
+
98
+ /* Legacy Aliases — map old variable names to new token system */
99
+ --ink: var(--tsu-fg);
100
+ --muted: var(--tsu-neutral-11);
101
+ --accent: var(--tsu-accent-9);
102
+ --surface: var(--tsu-bg);
103
+ --bg: var(--tsu-neutral-2);
104
+ --border: var(--tsu-neutral-7);
105
+ --danger: var(--tsu-danger-9);
106
+ }
107
+
108
+ /* Dark mode: use a lighter page background */
109
+ :root.dark {
110
+ --tsu-bg: var(--tsu-neutral-3);
111
+ --tsu-fg: #ffffff;
112
+ }
@@ -0,0 +1 @@
1
+ @import './reset.css';
@@ -0,0 +1,27 @@
1
+ :root {
2
+ --tsu-radius-round: 9999px;
3
+
4
+ --tsu-radius-l3-xs: 16px;
5
+ --tsu-radius-l2-xs: 8px;
6
+ --tsu-radius-l1-xs: 2px;
7
+
8
+ --tsu-radius-l3-sm: 16px;
9
+ --tsu-radius-l2-sm: 8px;
10
+ --tsu-radius-l1-sm: 2px;
11
+
12
+ --tsu-radius-l3-md: 16px;
13
+ --tsu-radius-l2-md: 8px;
14
+ --tsu-radius-l1-md: 4px;
15
+
16
+ --tsu-radius-l3-lg: 16px;
17
+ --tsu-radius-l2-lg: 8px;
18
+ --tsu-radius-l1-lg: 6px;
19
+
20
+ --tsu-radius-l3-xl: 16px;
21
+ --tsu-radius-l2-xl: 8px;
22
+ --tsu-radius-l1-xl: 8px;
23
+
24
+ --tsu-radius-l3-xxl: 16px;
25
+ --tsu-radius-l2-xxl: 8px;
26
+ --tsu-radius-l1-xxl: 16px;
27
+ }
@@ -0,0 +1,111 @@
1
+ @import './tokens.css';
2
+
3
+ /* ── Modern CSS Reset ─────────────────────────────────────────────── */
4
+ *,
5
+ *::before,
6
+ *::after {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ html {
11
+ -moz-text-size-adjust: none;
12
+ -webkit-text-size-adjust: none;
13
+ text-size-adjust: none;
14
+ }
15
+
16
+ * {
17
+ margin: 0;
18
+ padding: 0;
19
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
20
+ }
21
+
22
+ body {
23
+ min-height: 100vh;
24
+ font-family: var(--tsu-font-family);
25
+ font-size: var(--tsu-font-size-md);
26
+ line-height: var(--tsu-line-height);
27
+ color: var(--tsu-fg);
28
+ background-color: var(--tsu-bg);
29
+ text-rendering: optimizeLegibility;
30
+ -webkit-font-smoothing: antialiased;
31
+ -moz-osx-font-smoothing: grayscale;
32
+ }
33
+
34
+ img,
35
+ picture,
36
+ video,
37
+ canvas,
38
+ svg {
39
+ display: block;
40
+ max-inline-size: 100%;
41
+ }
42
+
43
+ input,
44
+ button,
45
+ textarea,
46
+ select {
47
+ font: inherit;
48
+ color: inherit;
49
+ }
50
+
51
+ p,
52
+ h1,
53
+ h2,
54
+ h3,
55
+ h4,
56
+ h5,
57
+ h6 {
58
+ overflow-wrap: break-word;
59
+ }
60
+
61
+ p {
62
+ text-wrap: pretty;
63
+ }
64
+
65
+ h1,
66
+ h2,
67
+ h3,
68
+ h4,
69
+ h5,
70
+ h6 {
71
+ text-wrap: balance;
72
+ font-weight: 600;
73
+ }
74
+
75
+ a {
76
+ color: inherit;
77
+ text-decoration: none;
78
+ }
79
+
80
+ textarea:not([rows]) {
81
+ min-height: 10em;
82
+ }
83
+
84
+ :target {
85
+ scroll-margin-block: 5ex;
86
+ }
87
+
88
+ :where(ul, ol) {
89
+ list-style: none;
90
+ }
91
+
92
+ :where(table) {
93
+ border-collapse: collapse;
94
+ border-spacing: 0;
95
+ }
96
+
97
+ :where(button) {
98
+ appearance: none;
99
+ background: none;
100
+ border: none;
101
+ cursor: pointer;
102
+ }
103
+
104
+ :where([hidden]) {
105
+ display: none;
106
+ }
107
+
108
+ input[type="search"]::-webkit-search-cancel-button,
109
+ input[type="search"]::-ms-clear {
110
+ display: none;
111
+ }
@@ -0,0 +1,5 @@
1
+ :root {
2
+ --tsu-shadow-sm: 0 1px 2px var(--tsu-neutral-alpha-6);
3
+ --tsu-shadow-md: 0 4px 12px var(--tsu-neutral-alpha-8);
4
+ --tsu-shadow-lg: 0 8px 24px var(--tsu-neutral-alpha-10);
5
+ }