premium-ds 0.1.0

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 (257) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +113 -0
  3. package/dist/alert.d.ts +31 -0
  4. package/dist/alert.js +6 -0
  5. package/dist/alert.js.map +1 -0
  6. package/dist/avatar-group.d.ts +13 -0
  7. package/dist/avatar-group.js +3 -0
  8. package/dist/avatar-group.js.map +1 -0
  9. package/dist/avatar.d.ts +25 -0
  10. package/dist/avatar.js +3 -0
  11. package/dist/avatar.js.map +1 -0
  12. package/dist/badge.d.ts +23 -0
  13. package/dist/badge.js +3 -0
  14. package/dist/badge.js.map +1 -0
  15. package/dist/button.d.ts +20 -0
  16. package/dist/button.js +3 -0
  17. package/dist/button.js.map +1 -0
  18. package/dist/checkbox.d.ts +25 -0
  19. package/dist/checkbox.js +3 -0
  20. package/dist/checkbox.js.map +1 -0
  21. package/dist/chunk-2OWHZ4JT.js +36 -0
  22. package/dist/chunk-2OWHZ4JT.js.map +1 -0
  23. package/dist/chunk-34SIXSYL.js +64 -0
  24. package/dist/chunk-34SIXSYL.js.map +1 -0
  25. package/dist/chunk-37O2ZXD6.js +55 -0
  26. package/dist/chunk-37O2ZXD6.js.map +1 -0
  27. package/dist/chunk-4AZL76UJ.js +89 -0
  28. package/dist/chunk-4AZL76UJ.js.map +1 -0
  29. package/dist/chunk-4HSCN5TZ.js +86 -0
  30. package/dist/chunk-4HSCN5TZ.js.map +1 -0
  31. package/dist/chunk-5DDOOT33.js +258 -0
  32. package/dist/chunk-5DDOOT33.js.map +1 -0
  33. package/dist/chunk-5FVHWIMY.js +117 -0
  34. package/dist/chunk-5FVHWIMY.js.map +1 -0
  35. package/dist/chunk-5K6KRJGX.js +147 -0
  36. package/dist/chunk-5K6KRJGX.js.map +1 -0
  37. package/dist/chunk-5PQMQBQC.js +74 -0
  38. package/dist/chunk-5PQMQBQC.js.map +1 -0
  39. package/dist/chunk-7OCTVQ7C.js +95 -0
  40. package/dist/chunk-7OCTVQ7C.js.map +1 -0
  41. package/dist/chunk-7OPMOET7.js +39 -0
  42. package/dist/chunk-7OPMOET7.js.map +1 -0
  43. package/dist/chunk-BXXS7YRC.js +270 -0
  44. package/dist/chunk-BXXS7YRC.js.map +1 -0
  45. package/dist/chunk-CV2Q4YXX.js +272 -0
  46. package/dist/chunk-CV2Q4YXX.js.map +1 -0
  47. package/dist/chunk-EIMMDWIW.js +282 -0
  48. package/dist/chunk-EIMMDWIW.js.map +1 -0
  49. package/dist/chunk-EZ2CWTBE.js +230 -0
  50. package/dist/chunk-EZ2CWTBE.js.map +1 -0
  51. package/dist/chunk-FGHDG3Y4.js +89 -0
  52. package/dist/chunk-FGHDG3Y4.js.map +1 -0
  53. package/dist/chunk-FPP2XLKX.js +127 -0
  54. package/dist/chunk-FPP2XLKX.js.map +1 -0
  55. package/dist/chunk-G6OY35DI.js +295 -0
  56. package/dist/chunk-G6OY35DI.js.map +1 -0
  57. package/dist/chunk-H6KWJNOE.js +65 -0
  58. package/dist/chunk-H6KWJNOE.js.map +1 -0
  59. package/dist/chunk-HGILYGY3.js +45 -0
  60. package/dist/chunk-HGILYGY3.js.map +1 -0
  61. package/dist/chunk-I3BCB4Z5.js +88 -0
  62. package/dist/chunk-I3BCB4Z5.js.map +1 -0
  63. package/dist/chunk-KBWNUUWM.js +582 -0
  64. package/dist/chunk-KBWNUUWM.js.map +1 -0
  65. package/dist/chunk-KN7JFAZ6.js +113 -0
  66. package/dist/chunk-KN7JFAZ6.js.map +1 -0
  67. package/dist/chunk-MEF7PI6U.js +16 -0
  68. package/dist/chunk-MEF7PI6U.js.map +1 -0
  69. package/dist/chunk-NKGMQL6I.js +310 -0
  70. package/dist/chunk-NKGMQL6I.js.map +1 -0
  71. package/dist/chunk-NMFQRGLL.js +127 -0
  72. package/dist/chunk-NMFQRGLL.js.map +1 -0
  73. package/dist/chunk-OUBWD6CX.js +433 -0
  74. package/dist/chunk-OUBWD6CX.js.map +1 -0
  75. package/dist/chunk-PFNXVBLU.js +96 -0
  76. package/dist/chunk-PFNXVBLU.js.map +1 -0
  77. package/dist/chunk-PUPZ4HME.js +165 -0
  78. package/dist/chunk-PUPZ4HME.js.map +1 -0
  79. package/dist/chunk-QFS52OK5.js +690 -0
  80. package/dist/chunk-QFS52OK5.js.map +1 -0
  81. package/dist/chunk-QNC6O3PG.js +45 -0
  82. package/dist/chunk-QNC6O3PG.js.map +1 -0
  83. package/dist/chunk-QUHOXWBK.js +82 -0
  84. package/dist/chunk-QUHOXWBK.js.map +1 -0
  85. package/dist/chunk-UIQGSTBJ.js +106 -0
  86. package/dist/chunk-UIQGSTBJ.js.map +1 -0
  87. package/dist/chunk-UJQKVP6V.js +193 -0
  88. package/dist/chunk-UJQKVP6V.js.map +1 -0
  89. package/dist/chunk-VVPGEAC6.js +11 -0
  90. package/dist/chunk-VVPGEAC6.js.map +1 -0
  91. package/dist/chunk-XA3T5KWA.js +58 -0
  92. package/dist/chunk-XA3T5KWA.js.map +1 -0
  93. package/dist/chunk-YSHJHSJM.js +19 -0
  94. package/dist/chunk-YSHJHSJM.js.map +1 -0
  95. package/dist/chunk-YVHOAVSM.js +182 -0
  96. package/dist/chunk-YVHOAVSM.js.map +1 -0
  97. package/dist/collapse.d.ts +16 -0
  98. package/dist/collapse.js +3 -0
  99. package/dist/collapse.js.map +1 -0
  100. package/dist/count-badge.d.ts +11 -0
  101. package/dist/count-badge.js +4 -0
  102. package/dist/count-badge.js.map +1 -0
  103. package/dist/date-field.d.ts +39 -0
  104. package/dist/date-field.js +8 -0
  105. package/dist/date-field.js.map +1 -0
  106. package/dist/date-range-field.d.ts +30 -0
  107. package/dist/date-range-field.js +8 -0
  108. package/dist/date-range-field.js.map +1 -0
  109. package/dist/datetime-field.d.ts +28 -0
  110. package/dist/datetime-field.js +10 -0
  111. package/dist/datetime-field.js.map +1 -0
  112. package/dist/dialog.d.ts +26 -0
  113. package/dist/dialog.js +7 -0
  114. package/dist/dialog.js.map +1 -0
  115. package/dist/index.d.ts +35 -0
  116. package/dist/index.js +40 -0
  117. package/dist/index.js.map +1 -0
  118. package/dist/motion-tokens.d.ts +29 -0
  119. package/dist/motion-tokens.js +3 -0
  120. package/dist/motion-tokens.js.map +1 -0
  121. package/dist/multi-select.d.ts +25 -0
  122. package/dist/multi-select.js +7 -0
  123. package/dist/multi-select.js.map +1 -0
  124. package/dist/number-field.d.ts +24 -0
  125. package/dist/number-field.js +4 -0
  126. package/dist/number-field.js.map +1 -0
  127. package/dist/otp-field.d.ts +20 -0
  128. package/dist/otp-field.js +3 -0
  129. package/dist/otp-field.js.map +1 -0
  130. package/dist/overlay.d.ts +31 -0
  131. package/dist/overlay.js +4 -0
  132. package/dist/overlay.js.map +1 -0
  133. package/dist/pagination.d.ts +24 -0
  134. package/dist/pagination.js +5 -0
  135. package/dist/pagination.js.map +1 -0
  136. package/dist/radio-group.d.ts +46 -0
  137. package/dist/radio-group.js +6 -0
  138. package/dist/radio-group.js.map +1 -0
  139. package/dist/select-core-SAyS-8w0.d.ts +16 -0
  140. package/dist/select.d.ts +27 -0
  141. package/dist/select.js +7 -0
  142. package/dist/select.js.map +1 -0
  143. package/dist/status-badge.d.ts +17 -0
  144. package/dist/status-badge.js +5 -0
  145. package/dist/status-badge.js.map +1 -0
  146. package/dist/table.d.ts +65 -0
  147. package/dist/table.js +5 -0
  148. package/dist/table.js.map +1 -0
  149. package/dist/tabs.d.ts +44 -0
  150. package/dist/tabs.js +5 -0
  151. package/dist/tabs.js.map +1 -0
  152. package/dist/tag.d.ts +28 -0
  153. package/dist/tag.js +5 -0
  154. package/dist/tag.js.map +1 -0
  155. package/dist/text-field.d.ts +30 -0
  156. package/dist/text-field.js +6 -0
  157. package/dist/text-field.js.map +1 -0
  158. package/dist/textarea.d.ts +33 -0
  159. package/dist/textarea.js +5 -0
  160. package/dist/textarea.js.map +1 -0
  161. package/dist/time-field.d.ts +27 -0
  162. package/dist/time-field.js +6 -0
  163. package/dist/time-field.js.map +1 -0
  164. package/dist/toast-store.d.ts +75 -0
  165. package/dist/toast-store.js +3 -0
  166. package/dist/toast-store.js.map +1 -0
  167. package/dist/toast.d.ts +3 -0
  168. package/dist/toast.js +6 -0
  169. package/dist/toast.js.map +1 -0
  170. package/dist/toggle-tag.d.ts +24 -0
  171. package/dist/toggle-tag.js +4 -0
  172. package/dist/toggle-tag.js.map +1 -0
  173. package/dist/toggle.d.ts +21 -0
  174. package/dist/toggle.js +3 -0
  175. package/dist/toggle.js.map +1 -0
  176. package/dist/tooltip.d.ts +27 -0
  177. package/dist/tooltip.js +4 -0
  178. package/dist/tooltip.js.map +1 -0
  179. package/llms.txt +165 -0
  180. package/package.json +205 -0
  181. package/src/components/alert/Alert.tsx +118 -0
  182. package/src/components/alert/alert.css +136 -0
  183. package/src/components/avatar/Avatar.tsx +128 -0
  184. package/src/components/avatar/AvatarGroup.tsx +50 -0
  185. package/src/components/avatar/avatar.css +200 -0
  186. package/src/components/badge/Badge.tsx +66 -0
  187. package/src/components/badge/CountBadge.tsx +46 -0
  188. package/src/components/badge/StatusBadge.tsx +132 -0
  189. package/src/components/badge/badge.css +243 -0
  190. package/src/components/button/Button.tsx +68 -0
  191. package/src/components/button/button.css +222 -0
  192. package/src/components/checkbox/Checkbox.tsx +90 -0
  193. package/src/components/checkbox/checkbox.css +179 -0
  194. package/src/components/date-picker/DateField.tsx +362 -0
  195. package/src/components/date-picker/DateRangeField.tsx +533 -0
  196. package/src/components/date-picker/DateTimeField.tsx +177 -0
  197. package/src/components/date-picker/TimeField.tsx +100 -0
  198. package/src/components/date-picker/date-picker.css +591 -0
  199. package/src/components/date-picker/date-utils.ts +55 -0
  200. package/src/components/date-picker/field-shell.tsx +78 -0
  201. package/src/components/date-picker/glide-pill.tsx +81 -0
  202. package/src/components/date-picker/time-core.tsx +305 -0
  203. package/src/components/dialog/Dialog.tsx +181 -0
  204. package/src/components/dialog/dialog.css +170 -0
  205. package/src/components/glass/glass.css +100 -0
  206. package/src/components/icon/Icon.tsx +76 -0
  207. package/src/components/icon/IconSlot.tsx +11 -0
  208. package/src/components/icon/icon.css +33 -0
  209. package/src/components/input/NumberField.tsx +117 -0
  210. package/src/components/input/OtpField.tsx +118 -0
  211. package/src/components/input/TextField.tsx +123 -0
  212. package/src/components/input/input.css +335 -0
  213. package/src/components/motion/Collapse.tsx +33 -0
  214. package/src/components/motion/collapse.css +41 -0
  215. package/src/components/overlay/Overlay.tsx +239 -0
  216. package/src/components/overlay/overlay-core.tsx +565 -0
  217. package/src/components/overlay/overlay.css +119 -0
  218. package/src/components/overlay/sheet-drag.tsx +146 -0
  219. package/src/components/pagination/Pagination.tsx +140 -0
  220. package/src/components/pagination/pagination.css +48 -0
  221. package/src/components/radio-group/RadioGroup.tsx +182 -0
  222. package/src/components/radio-group/radio-group.css +277 -0
  223. package/src/components/select/MultiSelect.tsx +251 -0
  224. package/src/components/select/Select.tsx +235 -0
  225. package/src/components/select/select-core.tsx +417 -0
  226. package/src/components/select/select.css +386 -0
  227. package/src/components/table/Table.tsx +433 -0
  228. package/src/components/table/table.css +348 -0
  229. package/src/components/tabs/Tabs.tsx +371 -0
  230. package/src/components/tabs/tabs.css +228 -0
  231. package/src/components/tag/Tag.tsx +145 -0
  232. package/src/components/tag/ToggleTag.tsx +125 -0
  233. package/src/components/tag/tag.css +248 -0
  234. package/src/components/textarea/Textarea.tsx +197 -0
  235. package/src/components/textarea/textarea.css +219 -0
  236. package/src/components/toast/Toast.tsx +349 -0
  237. package/src/components/toast/toast-store.ts +266 -0
  238. package/src/components/toast/toast.css +233 -0
  239. package/src/components/toggle/Toggle.tsx +94 -0
  240. package/src/components/toggle/toggle.css +152 -0
  241. package/src/components/tooltip/Tooltip.tsx +365 -0
  242. package/src/components/tooltip/tooltip.css +86 -0
  243. package/src/index.ts +42 -0
  244. package/src/styles.css +39 -0
  245. package/src/tokens/avatar.css +20 -0
  246. package/src/tokens/color.css +56 -0
  247. package/src/tokens/elevation.css +20 -0
  248. package/src/tokens/fonts.css +3 -0
  249. package/src/tokens/glass.css +21 -0
  250. package/src/tokens/icons.css +7 -0
  251. package/src/tokens/layers.css +6 -0
  252. package/src/tokens/motion-tokens.ts +72 -0
  253. package/src/tokens/motion.css +49 -0
  254. package/src/tokens/radius.css +11 -0
  255. package/src/tokens/semantic.css +75 -0
  256. package/src/tokens/spacing.css +26 -0
  257. package/src/tokens/typography.css +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tabsir Ahammed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # premium-ds
2
+
3
+ A premium React design system - modern CSS + a small, closed token vocabulary, applied
4
+ consistently. Restraint, calm motion, no Tailwind, no CSS-in-JS, no UI libraries.
5
+
6
+ **React 19 - TypeScript - ships compiled ESM + types.** Import the whole library or a single
7
+ component; link one stylesheet.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pnpm add premium-ds
13
+ # peers (you likely already have them):
14
+ pnpm add react react-dom motion
15
+ ```
16
+
17
+ | Peer | Range | Used for |
18
+ | --------------------- | ----- | -------------------------------------------------------------------- |
19
+ | `react` / `react-dom` | `^19` | components; `createRoot`/`createPortal` for imperative toast/tooltip |
20
+ | `motion` | `^12` | enter/exit + layout animation (`motion/react`) |
21
+
22
+ Icons are **bundled** (a small curated Phosphor set) - there is no icon peer to install.
23
+
24
+ ## Use it
25
+
26
+ No bundler config and no `transpilePackages` - the package ships built ESM with the `'use client'`
27
+ directives intact, so Next.js App Router boundaries just work.
28
+
29
+ ```tsx
30
+ import { Button, toast } from 'premium-ds';
31
+ import 'premium-ds/styles.css'; // link once, at the app root
32
+ ```
33
+
34
+ Link `styles.css` exactly once - it's the full token + component manifest
35
+ (fonts - primitives - semantics - components).
36
+
37
+ ### Import a single component
38
+
39
+ Every component is also a subpath export, so you can pull just one:
40
+
41
+ ```tsx
42
+ import { Button } from 'premium-ds/button';
43
+ import { DateField } from 'premium-ds/date-field';
44
+ ```
45
+
46
+ The barrel is side-effect-free and tree-shakes, so `import { Button } from 'premium-ds'` is
47
+ equally lean in a bundler - subpaths help in non-bundled or explicit setups.
48
+
49
+ ## Components
50
+
51
+ | Group | Components |
52
+ | ------------------- | --------------------------------------------------------------------------------------------- |
53
+ | Primitives | Button, Collapse, Badge, StatusBadge, CountBadge |
54
+ | Forms | TextField, NumberField, OtpField, Textarea, Checkbox, Toggle, RadioGroup, Select, MultiSelect |
55
+ | Data | Avatar, AvatarGroup, Tag, ToggleTag, Table, Pagination |
56
+ | Date, time & tabs | DateField, DateTimeField, DateRangeField, TimeField, Tabs |
57
+ | Overlays & feedback | Alert, Toast, Tooltip, Dialog, Overlay, Sheet |
58
+
59
+ Each is a named export from the barrel and a subpath (`premium-ds/<kebab-name>`). Props are
60
+ documented inline in the types; see [`llms.txt`](./llms.txt) for per-component examples.
61
+
62
+ ## For AI coding agents
63
+
64
+ Once installed, an agent doesn't need to read the component source - the contract is the shipped
65
+ types:
66
+
67
+ - **`node_modules/premium-ds/dist/*.d.ts`** - every component's props carry inline TSDoc. This is
68
+ the machine-readable source of truth (e.g. `dist/button.d.ts` fully describes `ButtonProps`).
69
+ - **`llms.txt`** (package root) - a compact, per-component index: purpose - import - a minimal
70
+ example. Cheaper to scan than every `.d.ts`.
71
+ - This README.
72
+
73
+ ## Copy-paste instead
74
+
75
+ The tarball also ships `src/`, so you can lift a component straight from
76
+ `node_modules/premium-ds/src/components/<name>/` into your project. Components aren't fully
77
+ self-contained - they share `src/tokens/`, the `motion-tokens` bridge, the internal `icon/`, and a
78
+ few `*-core` helpers - so copy those alongside. (A shadcn-style registry/CLI could automate this
79
+ later.)
80
+
81
+ ## Icons
82
+
83
+ Components render their own glyphs from a small curated Phosphor set, **bundled in** - no icon peer
84
+ to install. premium-ds does **not** export an `Icon` component, so where a prop takes an icon
85
+ (`iconLeft`, `leadingIcon`, a `Tag`'s `icon`, ...) pass your own node - any `ReactNode` (e.g. an
86
+ `@phosphor-icons/react` element, if you choose to use it).
87
+
88
+ ## What's inside
89
+
90
+ ```
91
+ src/ source (also shipped, for copy-paste)
92
+ -- index.ts public barrel
93
+ -- styles.css @import manifest (link once)
94
+ -- tokens/ CSS custom properties + motion-tokens.ts (JS and CSS motion bridge)
95
+ -- components/ <domain>/Name.tsx + name.css
96
+ dist/ compiled ESM + .d.ts - what you import
97
+ ```
98
+
99
+ ## Notes
100
+
101
+ - **Fonts.** `src/tokens/fonts.css` pulls Geist + Geist Mono from Google Fonts via a remote
102
+ `@import`. Self-host the families to drop the render-blocking network hop.
103
+ - **Styling is token-driven.** Re-skin by overriding the CSS custom properties in your own
104
+ stylesheet loaded after `premium-ds/styles.css` - never fork the source.
105
+
106
+ ## Develop
107
+
108
+ ```bash
109
+ pnpm install
110
+ pnpm build # tsup - dist/ (ESM + .d.ts)
111
+ pnpm typecheck # tsc --noEmit
112
+ pnpm format # prettier --write
113
+ ```
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+
3
+ type AlertTone = 'info' | 'success' | 'warning' | 'danger';
4
+ interface AlertAction {
5
+ /** Sentence-case label, e.g. "Update billing". */
6
+ label: string;
7
+ onClick?: () => void;
8
+ }
9
+ interface AlertProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
10
+ /** Status of the message; info/success are polite, warning/danger assertive. Default 'info'. */
11
+ tone?: AlertTone;
12
+ /** The message - sentence case, ideally one line. */
13
+ title: React.ReactNode;
14
+ /** Optional description; stays neutral - tone marks the message, not the prose. */
15
+ children?: React.ReactNode;
16
+ /** One action max, rendered as the system secondary small button. */
17
+ action?: AlertAction;
18
+ /** Renders the always-visible close button. Uncontrolled unless `open` is given. */
19
+ dismissible?: boolean;
20
+ /** Fires on dismiss. With `open` set, the parent owns hiding the alert. */
21
+ onDismiss?: () => void;
22
+ /** Controlled visibility; omit for uncontrolled. Exit eases shut (height collapse). */
23
+ open?: boolean;
24
+ /** App-level strip: square corners, hairline below only. Paint modifier. */
25
+ banner?: boolean;
26
+ /** Override the tone glyph; pass null to render no glyph. */
27
+ icon?: React.ReactNode | null;
28
+ }
29
+ declare function Alert({ tone, title, children, action, dismissible, onDismiss, open, banner, icon, className, ...rest }: AlertProps): React.JSX.Element;
30
+
31
+ export { Alert, type AlertAction, type AlertProps, type AlertTone };
package/dist/alert.js ADDED
@@ -0,0 +1,6 @@
1
+ 'use client';export { Alert } from './chunk-H6KWJNOE.js';
2
+ import './chunk-VVPGEAC6.js';
3
+ import './chunk-KBWNUUWM.js';
4
+ import './chunk-37O2ZXD6.js';
5
+ //# sourceMappingURL=alert.js.map
6
+ //# sourceMappingURL=alert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"alert.js"}
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import { AvatarSize } from './avatar.js';
3
+
4
+ interface AvatarGroupProps extends React.HTMLAttributes<HTMLSpanElement> {
5
+ children: React.ReactNode;
6
+ /** Max visible avatars before "+N" overflow chip. Default 5. */
7
+ max?: number;
8
+ /** Uniform size applied to all children. Default 'md'. */
9
+ size?: AvatarSize;
10
+ }
11
+ declare function AvatarGroup({ children, max, size, className, ...rest }: AvatarGroupProps): React.JSX.Element;
12
+
13
+ export { AvatarGroup, type AvatarGroupProps };
@@ -0,0 +1,3 @@
1
+ 'use client';export { AvatarGroup } from './chunk-7OPMOET7.js';
2
+ //# sourceMappingURL=avatar-group.js.map
3
+ //# sourceMappingURL=avatar-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"avatar-group.js"}
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+
3
+ type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
4
+ type AvatarShape = 'circle' | 'square';
5
+ type AvatarStatus = 'online' | 'away' | 'busy' | 'offline';
6
+ type AvatarPaletteIndex = 1 | 2 | 3 | 4 | 5 | 6;
7
+ interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {
8
+ /** Image URL. Falls back to initials / icon / silhouette if absent or fails. */
9
+ src?: string | null;
10
+ /** Display name - drives initials generation, palette hash, and aria-label. */
11
+ name?: string | null;
12
+ /** Content override - any React node (e.g. <Icon name="globe" />). */
13
+ icon?: React.ReactNode | null;
14
+ /** 'circle' for people; 'square' for channels / brand pages. Default 'circle'. */
15
+ shape?: AvatarShape;
16
+ /** Size step. Default 'md' (32 px). */
17
+ size?: AvatarSize;
18
+ /** Presence indicator dot at bottom-right. Default null (hidden). */
19
+ status?: AvatarStatus | null;
20
+ /** Override identity slot 1-6 (blue - violet - plum - rose - clay - moss); auto from name hash when null, neutral when anonymous. */
21
+ paletteIndex?: AvatarPaletteIndex | null;
22
+ }
23
+ declare function Avatar({ src, name, icon, shape, size, status, paletteIndex, className, style, ...rest }: AvatarProps): React.JSX.Element;
24
+
25
+ export { Avatar, type AvatarPaletteIndex, type AvatarProps, type AvatarShape, type AvatarSize, type AvatarStatus };
package/dist/avatar.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use client';export { Avatar } from './chunk-I3BCB4Z5.js';
2
+ //# sourceMappingURL=avatar.js.map
3
+ //# sourceMappingURL=avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"avatar.js"}
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ type BadgeTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';
5
+ interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
6
+ /** Status hue. @default 'neutral' */
7
+ tone?: BadgeTone;
8
+ /** Surface. @default 'glass' */
9
+ variant?: 'glass' | 'outline';
10
+ /** @default 'md' */
11
+ size?: 'sm' | 'md';
12
+ /** Leading status dot. */
13
+ dot?: boolean;
14
+ /** Dot pulses (implies dot) - for in-progress status. */
15
+ live?: boolean;
16
+ /** Fully-rounded shape. */
17
+ pill?: boolean;
18
+ /** Optional leading <Icon> (overrides dot if both set). */
19
+ icon?: ReactNode;
20
+ }
21
+ declare function Badge({ tone, variant, size, dot, live, pill, icon, className, children, ...rest }: BadgeProps): React.JSX.Element;
22
+
23
+ export { Badge, type BadgeProps, type BadgeTone };
package/dist/badge.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use client';export { Badge } from './chunk-2OWHZ4JT.js';
2
+ //# sourceMappingURL=badge.js.map
3
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"badge.js"}
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import { ButtonHTMLAttributes, ReactNode } from 'react';
3
+
4
+ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
5
+ /** Visual weight / intent. @default 'primary' */
6
+ variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
7
+ /** Control height. sm 28px - md 36px (default) - lg 40px. @default 'md' */
8
+ size?: 'sm' | 'md' | 'lg';
9
+ /** Loading - swaps content for a spinner and makes the button inert. */
10
+ loading?: boolean;
11
+ /** Leading icon node (e.g. a 16px <Icon>). Sized & aligned by the component. */
12
+ iconLeft?: ReactNode;
13
+ /** Trailing icon node. */
14
+ iconRight?: ReactNode;
15
+ /** Stretch to fill the container width. */
16
+ fullWidth?: boolean;
17
+ }
18
+ declare function Button({ variant, size, type, disabled, loading, iconLeft, iconRight, fullWidth, className, children, ...rest }: ButtonProps): React.JSX.Element;
19
+
20
+ export { Button, type ButtonProps };
package/dist/button.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use client';export { Button } from './chunk-HGILYGY3.js';
2
+ //# sourceMappingURL=button.js.map
3
+ //# sourceMappingURL=button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"button.js"}
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+
3
+ interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {
4
+ /** Controlled checked state. Omit for uncontrolled (use `defaultChecked`). */
5
+ checked?: boolean;
6
+ /** Uncontrolled initial state. */
7
+ defaultChecked?: boolean;
8
+ /** Indeterminate - the "some, not all" select-all state; visually wins over `checked`. @default false */
9
+ indeterminate?: boolean;
10
+ /** Single error state for consent gates ("you must agree"); also sets `aria-invalid`. @default false */
11
+ invalid?: boolean;
12
+ /** Disabled - inert and de-emphasized (distinct fill when checked). */
13
+ disabled?: boolean;
14
+ /** Box size: `md` 18px - `sm` 16px for dense table rows. @default 'md' */
15
+ size?: 'sm' | 'md';
16
+ /** Label text beside the box. */
17
+ label?: React.ReactNode;
18
+ /** Optional secondary line under the label (settings rows). */
19
+ description?: React.ReactNode;
20
+ /** Fires on toggle - read `e.target.checked`. */
21
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
22
+ }
23
+ declare function Checkbox({ checked, defaultChecked, indeterminate, invalid, disabled, size, label, description, className, onChange, ...rest }: CheckboxProps): React.JSX.Element;
24
+
25
+ export { Checkbox, type CheckboxProps };
@@ -0,0 +1,3 @@
1
+ 'use client';export { Checkbox } from './chunk-XA3T5KWA.js';
2
+ //# sourceMappingURL=checkbox.js.map
3
+ //# sourceMappingURL=checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"checkbox.js"}
@@ -0,0 +1,36 @@
1
+ 'use client';import { jsxs, jsx } from 'react/jsx-runtime';
2
+
3
+ // src/components/badge/Badge.tsx
4
+ function Badge({
5
+ tone = "neutral",
6
+ variant = "glass",
7
+ size = "md",
8
+ dot = false,
9
+ live = false,
10
+ pill = false,
11
+ icon = null,
12
+ className = "",
13
+ children,
14
+ ...rest
15
+ }) {
16
+ const isGlass = variant !== "outline";
17
+ const classes = [
18
+ isGlass ? "glass glass--interactive" : "",
19
+ "badge",
20
+ `badge--${tone}`,
21
+ variant === "outline" ? "badge--outline" : "",
22
+ size !== "md" ? `badge--${size}` : "",
23
+ pill ? "badge--pill" : "",
24
+ className
25
+ ].filter(Boolean).join(" ");
26
+ const showDot = (dot || live) && !icon;
27
+ return /* @__PURE__ */ jsxs("span", { className: classes, ...rest, children: [
28
+ showDot ? /* @__PURE__ */ jsx("span", { className: `badge__dot${live ? " badge__dot--live" : ""}`, "aria-hidden": "true" }) : null,
29
+ icon ? /* @__PURE__ */ jsx("span", { className: "badge__icon", "aria-hidden": "true", children: icon }) : null,
30
+ /* @__PURE__ */ jsx("span", { className: "badge__label", children })
31
+ ] });
32
+ }
33
+
34
+ export { Badge };
35
+ //# sourceMappingURL=chunk-2OWHZ4JT.js.map
36
+ //# sourceMappingURL=chunk-2OWHZ4JT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/badge/Badge.tsx"],"names":[],"mappings":";;;AAyBO,SAAS,KAAA,CAAM;AAAA,EACpB,IAAA,GAAO,SAAA;AAAA,EACP,OAAA,GAAU,OAAA;AAAA,EACV,IAAA,GAAO,IAAA;AAAA,EACP,GAAA,GAAM,KAAA;AAAA,EACN,IAAA,GAAO,KAAA;AAAA,EACP,IAAA,GAAO,KAAA;AAAA,EACP,IAAA,GAAO,IAAA;AAAA,EACP,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAe;AACb,EAAA,MAAM,UAAU,OAAA,KAAY,SAAA;AAC5B,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,UAAU,0BAAA,GAA6B,EAAA;AAAA,IACvC,OAAA;AAAA,IACA,UAAU,IAAI,CAAA,CAAA;AAAA,IACd,OAAA,KAAY,YAAY,gBAAA,GAAmB,EAAA;AAAA,IAC3C,IAAA,KAAS,IAAA,GAAO,CAAA,OAAA,EAAU,IAAI,CAAA,CAAA,GAAK,EAAA;AAAA,IACnC,OAAO,aAAA,GAAgB,EAAA;AAAA,IACvB;AAAA,GACF,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAEX,EAAA,MAAM,OAAA,GAAA,CAAW,GAAA,IAAO,IAAA,KAAS,CAAC,IAAA;AAElC,EAAA,uBACE,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,OAAA,EAAU,GAAG,IAAA,EAC3B,QAAA,EAAA;AAAA,IAAA,OAAA,mBACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,CAAA,UAAA,EAAa,IAAA,GAAO,sBAAsB,EAAE,CAAA,CAAA,EAAI,aAAA,EAAY,MAAA,EAAO,CAAA,GAClF,IAAA;AAAA,IACH,IAAA,uBACE,MAAA,EAAA,EAAK,SAAA,EAAU,eAAc,aAAA,EAAY,MAAA,EACvC,gBACH,CAAA,GACE,IAAA;AAAA,oBACJ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,cAAA,EAAgB,QAAA,EAAS;AAAA,GAAA,EAC3C,CAAA;AAEJ","file":"chunk-2OWHZ4JT.js","sourcesContent":["'use client';\n\n// Base badge chip - glass surface by default; the outline variant is flat (no glass classes).\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type BadgeTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n /** Status hue. @default 'neutral' */\n tone?: BadgeTone;\n /** Surface. @default 'glass' */\n variant?: 'glass' | 'outline';\n /** @default 'md' */\n size?: 'sm' | 'md';\n /** Leading status dot. */\n dot?: boolean;\n /** Dot pulses (implies dot) - for in-progress status. */\n live?: boolean;\n /** Fully-rounded shape. */\n pill?: boolean;\n /** Optional leading <Icon> (overrides dot if both set). */\n icon?: ReactNode;\n}\n\nexport function Badge({\n tone = 'neutral',\n variant = 'glass',\n size = 'md',\n dot = false,\n live = false,\n pill = false,\n icon = null,\n className = '',\n children,\n ...rest\n}: BadgeProps) {\n const isGlass = variant !== 'outline';\n const classes = [\n isGlass ? 'glass glass--interactive' : '',\n 'badge',\n `badge--${tone}`,\n variant === 'outline' ? 'badge--outline' : '',\n size !== 'md' ? `badge--${size}` : '',\n pill ? 'badge--pill' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const showDot = (dot || live) && !icon;\n\n return (\n <span className={classes} {...rest}>\n {showDot ? (\n <span className={`badge__dot${live ? ' badge__dot--live' : ''}`} aria-hidden=\"true\" />\n ) : null}\n {icon ? (\n <span className=\"badge__icon\" aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span className=\"badge__label\">{children}</span>\n </span>\n );\n}\n"]}
@@ -0,0 +1,64 @@
1
+ 'use client';import { TimeSegments } from './chunk-5DDOOT33.js';
2
+ import { useControllable, FieldShell } from './chunk-QNC6O3PG.js';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ function TimeField({
6
+ value,
7
+ // controlled: 'HH:mm' | null
8
+ defaultValue = null,
9
+ onChange,
10
+ label,
11
+ format = "24h",
12
+ minuteStep = 5,
13
+ min,
14
+ max,
15
+ required = false,
16
+ invalid = false,
17
+ message,
18
+ disabled = false,
19
+ className = ""
20
+ }) {
21
+ const [val, commit] = useControllable(value, defaultValue, onChange);
22
+ function onBoxPointerDown(e) {
23
+ if (disabled || e.target.closest(".tsg__seg")) return;
24
+ e.preventDefault();
25
+ const seg = e.currentTarget.querySelector(".tsg__seg");
26
+ if (seg) seg.focus();
27
+ }
28
+ return /* @__PURE__ */ jsx(
29
+ FieldShell,
30
+ {
31
+ variant: "tfd",
32
+ label,
33
+ required,
34
+ invalid,
35
+ message,
36
+ icon: "clock",
37
+ className,
38
+ children: /* @__PURE__ */ jsx(
39
+ "div",
40
+ {
41
+ className: "fld__input tfd__box" + (disabled ? " is-disabled" : ""),
42
+ onPointerDown: onBoxPointerDown,
43
+ children: /* @__PURE__ */ jsx(
44
+ TimeSegments,
45
+ {
46
+ value: val,
47
+ onCommit: commit,
48
+ format,
49
+ minuteStep,
50
+ min,
51
+ max,
52
+ disabled,
53
+ ariaLabel: label || "Time"
54
+ }
55
+ )
56
+ }
57
+ )
58
+ }
59
+ );
60
+ }
61
+
62
+ export { TimeField };
63
+ //# sourceMappingURL=chunk-34SIXSYL.js.map
64
+ //# sourceMappingURL=chunk-34SIXSYL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/date-picker/TimeField.tsx"],"names":[],"mappings":";;;;AA+CO,SAAS,SAAA,CAAU;AAAA,EACxB,KAAA;AAAA;AAAA,EACA,YAAA,GAAe,IAAA;AAAA,EACf,QAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA,EACT,UAAA,GAAa,CAAA;AAAA,EACb,GAAA;AAAA,EACA,GAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,OAAA,GAAU,KAAA;AAAA,EACV,OAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,SAAA,GAAY;AACd,CAAA,EAAmB;AACjB,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,IAAI,eAAA,CAAgB,KAAA,EAAO,cAAc,QAAQ,CAAA;AAGnE,EAAA,SAAS,iBAAiB,CAAA,EAAiC;AACzD,IAAA,IAAI,QAAA,IAAa,CAAA,CAAE,MAAA,CAAuB,OAAA,CAAQ,WAAW,CAAA,EAAG;AAChE,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,MAAM,GAAA,GAAM,CAAA,CAAE,aAAA,CAAc,aAAA,CAAc,WAAW,CAAA;AACrD,IAAA,IAAI,GAAA,MAAS,KAAA,EAAM;AAAA,EACrB;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,KAAA;AAAA,MACR,KAAA;AAAA,MACA,QAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA,EAAK,OAAA;AAAA,MACL,SAAA;AAAA,MAEA,QAAA,kBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,qBAAA,IAAyB,QAAA,GAAW,cAAA,GAAiB,EAAA,CAAA;AAAA,UAChE,aAAA,EAAe,gBAAA;AAAA,UAEf,QAAA,kBAAA,GAAA;AAAA,YAAC,YAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAO,GAAA;AAAA,cACP,QAAA,EAAU,MAAA;AAAA,cACV,MAAA;AAAA,cACA,UAAA;AAAA,cACA,GAAA;AAAA,cACA,GAAA;AAAA,cACA,QAAA;AAAA,cACA,WAAW,KAAA,IAAS;AAAA;AAAA;AACtB;AAAA;AACF;AAAA,GACF;AAEJ","file":"chunk-34SIXSYL.js","sourcesContent":["'use client';\n\n/* TimeField.tsx - standalone time field.\n -------------------------------------------------------------------------\n The segmented HH:MM machine (time-core.tsx) wearing the Input vocabulary -\n usable anywhere a bare time is needed, without the calendar.\n\n <TimeField\n label=\"Send at\"\n value=\"09:30\" // canonical 'HH:mm' (24h) | null\n onChange={(t) => ...} // live - the instant both segments exist\n format=\"12h\" // display only; storage stays 24h\n minuteStep={15} // ↑/↓ granularity (typing is exact)\n min=\"09:00\" max=\"17:30\" // saturation bounds - clamp, never error\n />\n\n Primitives consumed (A8): the .fld Input vocabulary (label/message/error\n chrome), TimeSegments (the machine), Icon. The box is a div wearing\n .fld__input - clicking its empty area seats focus in the hours segment.\n Buildless global was window.TimeField; a bundled app imports it. */\n\nimport type { PointerEvent } from 'react';\nimport { FieldShell, useControllable } from './field-shell';\nimport { TimeSegments } from './time-core';\n\nexport interface TimeFieldProps {\n /** Controlled value, canonical 'HH:mm' (24h). */\n value?: string | null;\n defaultValue?: string | null;\n /** Fires live - the instant both segments exist. */\n onChange?: (value: string) => void;\n label?: string;\n /** Display only; storage stays 24h. Default '24h'. */\n format?: '24h' | '12h';\n /** ↑/↓ step granularity in minutes (typing is exact). Default 5. */\n minuteStep?: number;\n /** Lower bound 'HH:mm' - saturates, never errors. */\n min?: string;\n /** Upper bound 'HH:mm' - saturates, never errors. */\n max?: string;\n required?: boolean;\n invalid?: boolean;\n message?: string;\n disabled?: boolean;\n className?: string;\n}\n\nexport function TimeField({\n value, // controlled: 'HH:mm' | null\n defaultValue = null,\n onChange,\n label,\n format = '24h',\n minuteStep = 5,\n min,\n max,\n required = false,\n invalid = false,\n message,\n disabled = false,\n className = '',\n}: TimeFieldProps) {\n const [val, commit] = useControllable(value, defaultValue, onChange);\n\n /* clicking the box (not a segment) seats focus where typing starts */\n function onBoxPointerDown(e: PointerEvent<HTMLDivElement>) {\n if (disabled || (e.target as HTMLElement).closest('.tsg__seg')) return;\n e.preventDefault();\n const seg = e.currentTarget.querySelector('.tsg__seg') as HTMLElement | null;\n if (seg) seg.focus();\n }\n\n return (\n <FieldShell\n variant=\"tfd\"\n label={label}\n required={required}\n invalid={invalid}\n message={message}\n icon=\"clock\"\n className={className}\n >\n <div\n className={'fld__input tfd__box' + (disabled ? ' is-disabled' : '')}\n onPointerDown={onBoxPointerDown}\n >\n <TimeSegments\n value={val}\n onCommit={commit}\n format={format}\n minuteStep={minuteStep}\n min={min}\n max={max}\n disabled={disabled}\n ariaLabel={label || 'Time'}\n />\n </div>\n </FieldShell>\n );\n}\n"]}
@@ -0,0 +1,55 @@
1
+ // src/tokens/motion-tokens.ts
2
+ var DEFAULT_DUR = { fast: 0.12, base: 0.18, slow: 0.26 };
3
+ var DEFAULT_EASE = {
4
+ standard: [0.2, 0, 0, 1],
5
+ entrance: [0.16, 1, 0.3, 1],
6
+ exit: [0.4, 0, 1, 1],
7
+ spring: [0.34, 1.4, 0.5, 1],
8
+ glide: [0.55, 0, 0.15, 1]
9
+ };
10
+ function build(dur, ease) {
11
+ const reduced = dur.base <= 5e-3;
12
+ return {
13
+ dur,
14
+ ease,
15
+ reduced,
16
+ t: {
17
+ enter: { duration: dur.base, ease: ease.entrance },
18
+ exit: { duration: dur.fast, ease: ease.exit },
19
+ layout: { duration: dur.slow, ease: ease.entrance },
20
+ settle: reduced ? { duration: 0 } : { type: "spring", visualDuration: dur.base, bounce: 0.22 }
21
+ }
22
+ };
23
+ }
24
+ function readFromDom() {
25
+ const cs = getComputedStyle(document.documentElement);
26
+ const seconds = (name, fallback) => {
27
+ const v = cs.getPropertyValue(name).trim();
28
+ const n = v.slice(-2) === "ms" ? parseFloat(v) / 1e3 : parseFloat(v);
29
+ return isNaN(n) ? fallback : n;
30
+ };
31
+ const bezier = (name, fallback) => {
32
+ const m = cs.getPropertyValue(name).match(/-?[\d.]+/g);
33
+ return m && m.length === 4 ? m.map(Number) : fallback;
34
+ };
35
+ return build(
36
+ {
37
+ fast: seconds("--duration-fast", DEFAULT_DUR.fast),
38
+ base: seconds("--duration-base", DEFAULT_DUR.base),
39
+ slow: seconds("--duration-slow", DEFAULT_DUR.slow)
40
+ },
41
+ {
42
+ standard: bezier("--ease-standard", DEFAULT_EASE.standard),
43
+ entrance: bezier("--ease-entrance", DEFAULT_EASE.entrance),
44
+ exit: bezier("--ease-exit", DEFAULT_EASE.exit),
45
+ spring: bezier("--ease-spring", DEFAULT_EASE.spring),
46
+ glide: bezier("--ease-glide", DEFAULT_EASE.glide)
47
+ }
48
+ );
49
+ }
50
+ var UIMotion = typeof document !== "undefined" ? readFromDom() : build(DEFAULT_DUR, DEFAULT_EASE);
51
+ var motion_tokens_default = UIMotion;
52
+
53
+ export { UIMotion, motion_tokens_default };
54
+ //# sourceMappingURL=chunk-37O2ZXD6.js.map
55
+ //# sourceMappingURL=chunk-37O2ZXD6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tokens/motion-tokens.ts"],"names":[],"mappings":";AAeA,IAAM,cAAmC,EAAE,IAAA,EAAM,MAAM,IAAA,EAAM,IAAA,EAAM,MAAM,IAAA,EAAK;AAC9E,IAAM,YAAA,GAAqC;AAAA,EACzC,QAAA,EAAU,CAAC,GAAA,EAAK,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,EACvB,QAAA,EAAU,CAAC,IAAA,EAAM,CAAA,EAAG,KAAK,CAAC,CAAA;AAAA,EAC1B,IAAA,EAAM,CAAC,GAAA,EAAK,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,EACnB,MAAA,EAAQ,CAAC,IAAA,EAAM,GAAA,EAAK,KAAK,CAAC,CAAA;AAAA,EAC1B,KAAA,EAAO,CAAC,IAAA,EAAM,CAAA,EAAG,MAAM,CAAC;AAC1B,CAAA;AAEA,SAAS,KAAA,CAAM,KAA0B,IAAA,EAA0C;AACjF,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,IAAQ,IAAA;AAC5B,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAA,EAAG;AAAA,MACD,OAAO,EAAE,QAAA,EAAU,IAAI,IAAA,EAAM,IAAA,EAAM,KAAK,QAAA,EAAS;AAAA,MACjD,MAAM,EAAE,QAAA,EAAU,IAAI,IAAA,EAAM,IAAA,EAAM,KAAK,IAAA,EAAK;AAAA,MAC5C,QAAQ,EAAE,QAAA,EAAU,IAAI,IAAA,EAAM,IAAA,EAAM,KAAK,QAAA,EAAS;AAAA,MAClD,MAAA,EAAQ,OAAA,GACJ,EAAE,QAAA,EAAU,CAAA,EAAE,GACd,EAAE,IAAA,EAAM,QAAA,EAAU,cAAA,EAAgB,GAAA,CAAI,IAAA,EAAM,QAAQ,IAAA;AAAK;AAC/D,GACF;AACF;AAEA,SAAS,WAAA,GAA4B;AACnC,EAAA,MAAM,EAAA,GAAK,gBAAA,CAAiB,QAAA,CAAS,eAAe,CAAA;AACpD,EAAA,MAAM,OAAA,GAAU,CAAC,IAAA,EAAc,QAAA,KAA6B;AAC1D,IAAA,MAAM,CAAA,GAAI,EAAA,CAAG,gBAAA,CAAiB,IAAI,EAAE,IAAA,EAAK;AACzC,IAAA,MAAM,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,EAAE,CAAA,KAAM,IAAA,GAAO,UAAA,CAAW,CAAC,CAAA,GAAI,GAAA,GAAO,UAAA,CAAW,CAAC,CAAA;AACpE,IAAA,OAAO,KAAA,CAAM,CAAC,CAAA,GAAI,QAAA,GAAW,CAAA;AAAA,EAC/B,CAAA;AACA,EAAA,MAAM,MAAA,GAAS,CAAC,IAAA,EAAc,QAAA,KAA6B;AACzD,IAAA,MAAM,IAAI,EAAA,CAAG,gBAAA,CAAiB,IAAI,CAAA,CAAE,MAAM,WAAW,CAAA;AACrD,IAAA,OAAO,KAAK,CAAA,CAAE,MAAA,KAAW,IAAK,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA,GAAe,QAAA;AAAA,EAC3D,CAAA;AACA,EAAA,OAAO,KAAA;AAAA,IACL;AAAA,MACE,IAAA,EAAM,OAAA,CAAQ,iBAAA,EAAmB,WAAA,CAAY,IAAI,CAAA;AAAA,MACjD,IAAA,EAAM,OAAA,CAAQ,iBAAA,EAAmB,WAAA,CAAY,IAAI,CAAA;AAAA,MACjD,IAAA,EAAM,OAAA,CAAQ,iBAAA,EAAmB,WAAA,CAAY,IAAI;AAAA,KACnD;AAAA,IACA;AAAA,MACE,QAAA,EAAU,MAAA,CAAO,iBAAA,EAAmB,YAAA,CAAa,QAAQ,CAAA;AAAA,MACzD,QAAA,EAAU,MAAA,CAAO,iBAAA,EAAmB,YAAA,CAAa,QAAQ,CAAA;AAAA,MACzD,IAAA,EAAM,MAAA,CAAO,aAAA,EAAe,YAAA,CAAa,IAAI,CAAA;AAAA,MAC7C,MAAA,EAAQ,MAAA,CAAO,eAAA,EAAiB,YAAA,CAAa,MAAM,CAAA;AAAA,MACnD,KAAA,EAAO,MAAA,CAAO,cAAA,EAAgB,YAAA,CAAa,KAAK;AAAA;AAClD,GACF;AACF;AAEO,IAAM,QAAA,GACX,OAAO,QAAA,KAAa,WAAA,GAAc,aAAY,GAAI,KAAA,CAAM,aAAa,YAAY;AAEnF,IAAO,qBAAA,GAAQ","file":"chunk-37O2ZXD6.js","sourcesContent":["/* motion-tokens.ts - the JSandCSS motion bridge; Motion code reads these token values, never hardcodes them. */\n\nimport type { Transition } from 'motion/react';\n\nexport type Bezier = [number, number, number, number];\n\nexport interface MotionTokens {\n /** seconds - fast 0.12 - base 0.18 - slow 0.26 */\n dur: { fast: number; base: number; slow: number };\n ease: { standard: Bezier; entrance: Bezier; exit: Bezier; spring: Bezier; glide: Bezier };\n /** ready-made Motion transitions */\n t: { enter: Transition; exit: Transition; layout: Transition; settle: Transition };\n reduced: boolean;\n}\n\nconst DEFAULT_DUR: MotionTokens['dur'] = { fast: 0.12, base: 0.18, slow: 0.26 };\nconst DEFAULT_EASE: MotionTokens['ease'] = {\n standard: [0.2, 0, 0, 1],\n entrance: [0.16, 1, 0.3, 1],\n exit: [0.4, 0, 1, 1],\n spring: [0.34, 1.4, 0.5, 1],\n glide: [0.55, 0, 0.15, 1],\n};\n\nfunction build(dur: MotionTokens['dur'], ease: MotionTokens['ease']): MotionTokens {\n const reduced = dur.base <= 0.005; // reduced motion collapses durations to ~1ms\n return {\n dur,\n ease,\n reduced,\n t: {\n enter: { duration: dur.base, ease: ease.entrance },\n exit: { duration: dur.fast, ease: ease.exit },\n layout: { duration: dur.slow, ease: ease.entrance },\n settle: reduced\n ? { duration: 0 }\n : { type: 'spring', visualDuration: dur.base, bounce: 0.22 },\n },\n };\n}\n\nfunction readFromDom(): MotionTokens {\n const cs = getComputedStyle(document.documentElement);\n const seconds = (name: string, fallback: number): number => {\n const v = cs.getPropertyValue(name).trim();\n const n = v.slice(-2) === 'ms' ? parseFloat(v) / 1000 : parseFloat(v);\n return isNaN(n) ? fallback : n;\n };\n const bezier = (name: string, fallback: Bezier): Bezier => {\n const m = cs.getPropertyValue(name).match(/-?[\\d.]+/g);\n return m && m.length === 4 ? (m.map(Number) as Bezier) : fallback;\n };\n return build(\n {\n fast: seconds('--duration-fast', DEFAULT_DUR.fast),\n base: seconds('--duration-base', DEFAULT_DUR.base),\n slow: seconds('--duration-slow', DEFAULT_DUR.slow),\n },\n {\n standard: bezier('--ease-standard', DEFAULT_EASE.standard),\n entrance: bezier('--ease-entrance', DEFAULT_EASE.entrance),\n exit: bezier('--ease-exit', DEFAULT_EASE.exit),\n spring: bezier('--ease-spring', DEFAULT_EASE.spring),\n glide: bezier('--ease-glide', DEFAULT_EASE.glide),\n },\n );\n}\n\nexport const UIMotion: MotionTokens =\n typeof document !== 'undefined' ? readFromDom() : build(DEFAULT_DUR, DEFAULT_EASE);\n\nexport default UIMotion;\n"]}
@@ -0,0 +1,89 @@
1
+ 'use client';import { IconSlot } from './chunk-VVPGEAC6.js';
2
+ import * as React from 'react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ var TOGGLE_TAG_OWN_PROPS = {
6
+ children: 1,
7
+ selected: 1,
8
+ defaultSelected: 1,
9
+ onChange: 1,
10
+ icon: 1,
11
+ count: 1,
12
+ size: 1,
13
+ disabled: 1,
14
+ className: 1
15
+ };
16
+ function toggleTagRestProps(props, own) {
17
+ const rest = {};
18
+ for (const k in props) {
19
+ if (!own[k]) rest[k] = props[k];
20
+ }
21
+ return rest;
22
+ }
23
+ function ToggleTagTick({ selected }) {
24
+ return /* @__PURE__ */ jsx(
25
+ "span",
26
+ {
27
+ className: "tag__check collapse",
28
+ "data-axis": "width",
29
+ "data-open": selected ? "true" : "false",
30
+ "aria-hidden": "true",
31
+ children: /* @__PURE__ */ jsx("span", { className: "collapse__inner", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx(
32
+ "path",
33
+ {
34
+ d: "M2.5 6.5 L5 9 L9.5 3.5",
35
+ pathLength: "1",
36
+ strokeWidth: "1.5",
37
+ strokeLinecap: "round",
38
+ strokeLinejoin: "round"
39
+ }
40
+ ) }) })
41
+ }
42
+ );
43
+ }
44
+ function ToggleTag(props) {
45
+ const {
46
+ children,
47
+ selected: controlledSelected,
48
+ defaultSelected = false,
49
+ onChange,
50
+ icon = null,
51
+ count = null,
52
+ size = "md",
53
+ disabled = false,
54
+ className = ""
55
+ } = props;
56
+ const rest = toggleTagRestProps(
57
+ props,
58
+ TOGGLE_TAG_OWN_PROPS
59
+ );
60
+ const [uncontrolled, setUncontrolled] = React.useState(defaultSelected);
61
+ const isControlled = controlledSelected !== void 0;
62
+ const selected = isControlled ? controlledSelected : uncontrolled;
63
+ function toggle() {
64
+ const next = !selected;
65
+ if (!isControlled) setUncontrolled(next);
66
+ if (onChange) onChange(next);
67
+ }
68
+ const classes = ["tag", "tag--toggle", size === "sm" ? "tag--sm" : "", className].filter(Boolean).join(" ");
69
+ return /* @__PURE__ */ jsxs(
70
+ "button",
71
+ {
72
+ type: "button",
73
+ className: classes,
74
+ "aria-pressed": selected,
75
+ disabled,
76
+ onClick: toggle,
77
+ ...rest,
78
+ children: [
79
+ icon ? /* @__PURE__ */ jsx("span", { className: "tag__icon", children: /* @__PURE__ */ jsx(IconSlot, { size: "sm", children: icon }) }) : /* @__PURE__ */ jsx(ToggleTagTick, { selected }),
80
+ /* @__PURE__ */ jsx("span", { className: "tag__label", children }),
81
+ count != null && /* @__PURE__ */ jsx("span", { className: "tag__count", children: count })
82
+ ]
83
+ }
84
+ );
85
+ }
86
+
87
+ export { ToggleTag };
88
+ //# sourceMappingURL=chunk-4AZL76UJ.js.map
89
+ //# sourceMappingURL=chunk-4AZL76UJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/tag/ToggleTag.tsx"],"names":[],"mappings":"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","file":"chunk-4AZL76UJ.js","sourcesContent":["'use client';\n\n/* ToggleTag - on/off filter chip (<button aria-pressed>); owns its selection state. */\n\nimport * as React from 'react';\nimport { IconSlot } from '../icon/IconSlot';\n\n/** ToggleTag - the on/off filter chip (<button aria-pressed>). */\nexport interface ToggleTagProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'onChange' | 'children'\n> {\n /** The label. */\n children: React.ReactNode;\n /** Controlled selected value. Omit for uncontrolled. */\n selected?: boolean;\n /** Uncontrolled initial value. */\n defaultSelected?: boolean;\n /** Fires with the next value on every toggle. */\n onChange?: (selected: boolean) => void;\n /** Your own icon node; replaces the tick. Selected state reads from the wash. */\n icon?: React.ReactNode | null;\n /** Optional result count - rendered mono/tabular. */\n count?: React.ReactNode;\n /** 'md' = 28px (default) - 'sm' = 24px for dense rows. */\n size?: 'md' | 'sm';\n disabled?: boolean;\n className?: string;\n}\n\n/* GOTCHA: split props manually instead of object-rest. */\nconst TOGGLE_TAG_OWN_PROPS: Record<string, number> = {\n children: 1,\n selected: 1,\n defaultSelected: 1,\n onChange: 1,\n icon: 1,\n count: 1,\n size: 1,\n disabled: 1,\n className: 1,\n};\nfunction toggleTagRestProps(props: Record<string, unknown>, own: Record<string, number>) {\n const rest: Record<string, unknown> = {};\n for (const k in props) {\n if (!own[k]) rest[k] = props[k];\n }\n return rest;\n}\n\nfunction ToggleTagTick({ selected }: { selected: boolean }) {\n /* collapse.css mechanism on spans - width 0fr and 1fr, content clipped */\n return (\n <span\n className=\"tag__check collapse\"\n data-axis=\"width\"\n data-open={selected ? 'true' : 'false'}\n aria-hidden=\"true\"\n >\n <span className=\"collapse__inner\">\n <svg viewBox=\"0 0 12 12\" fill=\"none\">\n <path\n d=\"M2.5 6.5 L5 9 L9.5 3.5\"\n pathLength=\"1\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </span>\n </span>\n );\n}\n\nexport function ToggleTag(props: ToggleTagProps) {\n const {\n children,\n selected: controlledSelected,\n defaultSelected = false,\n onChange,\n icon = null,\n count = null,\n size = 'md',\n disabled = false,\n className = '',\n } = props;\n const rest = toggleTagRestProps(\n props as unknown as Record<string, unknown>,\n TOGGLE_TAG_OWN_PROPS,\n );\n const [uncontrolled, setUncontrolled] = React.useState(defaultSelected);\n const isControlled = controlledSelected !== undefined;\n const selected = isControlled ? controlledSelected : uncontrolled;\n\n function toggle() {\n const next = !selected;\n if (!isControlled) setUncontrolled(next);\n if (onChange) onChange(next);\n }\n\n const classes = ['tag', 'tag--toggle', size === 'sm' ? 'tag--sm' : '', className]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button\n type=\"button\"\n className={classes}\n aria-pressed={selected}\n disabled={disabled}\n onClick={toggle}\n {...rest}\n >\n {icon ? (\n <span className=\"tag__icon\">\n <IconSlot size=\"sm\">{icon}</IconSlot>\n </span>\n ) : (\n <ToggleTagTick selected={selected} />\n )}\n <span className=\"tag__label\">{children}</span>\n {count != null && <span className=\"tag__count\">{count}</span>}\n </button>\n );\n}\n"]}