@puzzle-ui/ui 0.3.0 → 0.5.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 (240) hide show
  1. package/README.md +70 -70
  2. package/dist/components/actions/button/button.css +5 -2
  3. package/dist/components/actions/button-group/button-group.css +16 -17
  4. package/dist/components/data-display/badge/badge.css +15 -2
  5. package/dist/components/data-display/badge/index.cjs +13 -2
  6. package/dist/components/data-display/badge/index.cjs.map +1 -1
  7. package/dist/components/data-display/badge/index.d.cts +7 -2
  8. package/dist/components/data-display/badge/index.d.ts +7 -2
  9. package/dist/components/data-display/badge/index.js +13 -2
  10. package/dist/components/data-display/badge/index.js.map +1 -1
  11. package/dist/components/data-display/empty-state/empty-state.css +128 -0
  12. package/dist/components/data-display/empty-state/empty-state.utils.cjs +6 -0
  13. package/dist/components/data-display/empty-state/empty-state.utils.cjs.map +1 -0
  14. package/dist/components/data-display/empty-state/empty-state.utils.js +6 -0
  15. package/dist/components/data-display/empty-state/empty-state.utils.js.map +1 -0
  16. package/dist/components/data-display/empty-state/index.cjs +49 -0
  17. package/dist/components/data-display/empty-state/index.cjs.map +1 -0
  18. package/dist/components/data-display/empty-state/index.d.cts +19 -0
  19. package/dist/components/data-display/empty-state/index.d.ts +19 -0
  20. package/dist/components/data-display/empty-state/index.js +44 -0
  21. package/dist/components/data-display/empty-state/index.js.map +1 -0
  22. package/dist/components/data-display/rating/index.cjs +84 -0
  23. package/dist/components/data-display/rating/index.cjs.map +1 -0
  24. package/dist/components/data-display/rating/index.d.cts +3 -0
  25. package/dist/components/data-display/rating/index.d.ts +3 -0
  26. package/dist/components/data-display/rating/index.js +84 -0
  27. package/dist/components/data-display/rating/index.js.map +1 -0
  28. package/dist/components/data-display/rating/rating.css +72 -0
  29. package/dist/components/data-display/rating/rating.types.d.cts +15 -0
  30. package/dist/components/data-display/rating/rating.types.d.ts +15 -0
  31. package/dist/components/data-display/rating/rating.utils.cjs +27 -0
  32. package/dist/components/data-display/rating/rating.utils.cjs.map +1 -0
  33. package/dist/components/data-display/rating/rating.utils.js +25 -0
  34. package/dist/components/data-display/rating/rating.utils.js.map +1 -0
  35. package/dist/components/editors/text-editor/editor.cjs.map +1 -1
  36. package/dist/components/editors/text-editor/editor.js.map +1 -1
  37. package/dist/components/editors/text-editor/text-document.cjs.map +1 -1
  38. package/dist/components/editors/text-editor/text-document.js.map +1 -1
  39. package/dist/components/editors/text-editor/text-parser.cjs.map +1 -1
  40. package/dist/components/editors/text-editor/text-parser.js.map +1 -1
  41. package/dist/components/editors/text-editor/text-renderer.cjs.map +1 -1
  42. package/dist/components/editors/text-editor/text-renderer.js.map +1 -1
  43. package/dist/components/forms/autocomplete/index.cjs.map +1 -1
  44. package/dist/components/forms/autocomplete/index.js.map +1 -1
  45. package/dist/components/forms/checkbox/checkbox.css +2 -10
  46. package/dist/components/forms/color-picker/color-picker.css +351 -0
  47. package/dist/components/forms/color-picker/color-picker.types.d.cts +25 -0
  48. package/dist/components/forms/color-picker/color-picker.types.d.ts +25 -0
  49. package/dist/components/forms/color-picker/color-picker.utils.cjs +116 -0
  50. package/dist/components/forms/color-picker/color-picker.utils.cjs.map +1 -0
  51. package/dist/components/forms/color-picker/color-picker.utils.js +109 -0
  52. package/dist/components/forms/color-picker/color-picker.utils.js.map +1 -0
  53. package/dist/components/forms/color-picker/index.cjs +340 -0
  54. package/dist/components/forms/color-picker/index.cjs.map +1 -0
  55. package/dist/components/forms/color-picker/index.d.cts +3 -0
  56. package/dist/components/forms/color-picker/index.d.ts +3 -0
  57. package/dist/components/forms/color-picker/index.js +340 -0
  58. package/dist/components/forms/color-picker/index.js.map +1 -0
  59. package/dist/components/forms/file-upload/file-upload.utils.cjs.map +1 -1
  60. package/dist/components/forms/file-upload/file-upload.utils.js.map +1 -1
  61. package/dist/components/forms/input/number-input.js +5 -5
  62. package/dist/components/forms/input/number-input.js.map +1 -1
  63. package/dist/components/forms/input-group/index.d.cts +3 -0
  64. package/dist/components/forms/input-group/index.d.ts +3 -0
  65. package/dist/components/forms/input-group/input-group.cjs +18 -0
  66. package/dist/components/forms/input-group/input-group.cjs.map +1 -0
  67. package/dist/components/forms/input-group/input-group.css +62 -0
  68. package/dist/components/forms/input-group/input-group.d.cts +7 -0
  69. package/dist/components/forms/input-group/input-group.d.ts +7 -0
  70. package/dist/components/forms/input-group/input-group.js +18 -0
  71. package/dist/components/forms/input-group/input-group.js.map +1 -0
  72. package/dist/components/forms/input-group/input-group.types.d.cts +7 -0
  73. package/dist/components/forms/input-group/input-group.types.d.ts +7 -0
  74. package/dist/components/forms/input-group/input-group.utils.cjs +5 -0
  75. package/dist/components/forms/input-group/input-group.utils.cjs.map +1 -0
  76. package/dist/components/forms/input-group/input-group.utils.js +5 -0
  77. package/dist/components/forms/input-group/input-group.utils.js.map +1 -0
  78. package/dist/components/forms/radio-group/index.d.cts +2 -1
  79. package/dist/components/forms/radio-group/index.d.ts +2 -1
  80. package/dist/components/forms/select/index.cjs.map +1 -1
  81. package/dist/components/forms/select/index.js.map +1 -1
  82. package/dist/components/forms/slider/index.cjs +1 -1
  83. package/dist/components/forms/slider/index.cjs.map +1 -1
  84. package/dist/components/forms/slider/index.js +1 -1
  85. package/dist/components/forms/slider/index.js.map +1 -1
  86. package/dist/components/forms/stepper/index.d.cts +4 -2
  87. package/dist/components/forms/stepper/index.d.ts +4 -2
  88. package/dist/components/forms/time-picker/index.cjs +108 -0
  89. package/dist/components/forms/time-picker/index.cjs.map +1 -0
  90. package/dist/components/forms/time-picker/index.d.cts +3 -0
  91. package/dist/components/forms/time-picker/index.d.ts +3 -0
  92. package/dist/components/forms/time-picker/index.js +108 -0
  93. package/dist/components/forms/time-picker/index.js.map +1 -0
  94. package/dist/components/forms/time-picker/time-picker.css +166 -0
  95. package/dist/components/forms/time-picker/time-picker.types.d.cts +34 -0
  96. package/dist/components/forms/time-picker/time-picker.types.d.ts +34 -0
  97. package/dist/components/forms/time-picker/time-picker.utils.cjs +25 -0
  98. package/dist/components/forms/time-picker/time-picker.utils.cjs.map +1 -0
  99. package/dist/components/forms/time-picker/time-picker.utils.js +24 -0
  100. package/dist/components/forms/time-picker/time-picker.utils.js.map +1 -0
  101. package/dist/components/forms/token-input/index.cjs +189 -0
  102. package/dist/components/forms/token-input/index.cjs.map +1 -0
  103. package/dist/components/forms/token-input/index.d.cts +3 -0
  104. package/dist/components/forms/token-input/index.d.ts +3 -0
  105. package/dist/components/forms/token-input/index.js +189 -0
  106. package/dist/components/forms/token-input/index.js.map +1 -0
  107. package/dist/components/forms/token-input/token-input.css +145 -0
  108. package/dist/components/forms/token-input/token-input.types.d.cts +48 -0
  109. package/dist/components/forms/token-input/token-input.types.d.ts +48 -0
  110. package/dist/components/forms/token-input/token-input.utils.cjs +30 -0
  111. package/dist/components/forms/token-input/token-input.utils.cjs.map +1 -0
  112. package/dist/components/forms/token-input/token-input.utils.js +24 -0
  113. package/dist/components/forms/token-input/token-input.utils.js.map +1 -0
  114. package/dist/components/layout/aspect-ratio/aspect-ratio.css +14 -0
  115. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs +11 -0
  116. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs.map +1 -0
  117. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js +11 -0
  118. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js.map +1 -0
  119. package/dist/components/layout/aspect-ratio/index.cjs +16 -0
  120. package/dist/components/layout/aspect-ratio/index.cjs.map +1 -0
  121. package/dist/components/layout/aspect-ratio/index.d.cts +11 -0
  122. package/dist/components/layout/aspect-ratio/index.d.ts +11 -0
  123. package/dist/components/layout/aspect-ratio/index.js +16 -0
  124. package/dist/components/layout/aspect-ratio/index.js.map +1 -0
  125. package/dist/components/layout/container/container.css +1 -0
  126. package/dist/components/layout/page-layout/page-layout.css +1 -0
  127. package/dist/components/layout/resizable-panels/index.cjs +1 -1
  128. package/dist/components/layout/resizable-panels/index.cjs.map +1 -1
  129. package/dist/components/layout/resizable-panels/index.js +1 -1
  130. package/dist/components/layout/resizable-panels/index.js.map +1 -1
  131. package/dist/components/layout/resizable-panels/resizable-panels.utils.cjs.map +1 -1
  132. package/dist/components/layout/resizable-panels/resizable-panels.utils.js.map +1 -1
  133. package/dist/components/layout/scroll-area/index.cjs +27 -0
  134. package/dist/components/layout/scroll-area/index.cjs.map +1 -0
  135. package/dist/components/layout/scroll-area/index.d.cts +15 -0
  136. package/dist/components/layout/scroll-area/index.d.ts +15 -0
  137. package/dist/components/layout/scroll-area/index.js +27 -0
  138. package/dist/components/layout/scroll-area/index.js.map +1 -0
  139. package/dist/components/layout/scroll-area/scroll-area.css +25 -0
  140. package/dist/components/layout/scroll-area/scroll-area.utils.cjs +8 -0
  141. package/dist/components/layout/scroll-area/scroll-area.utils.cjs.map +1 -0
  142. package/dist/components/layout/scroll-area/scroll-area.utils.d.cts +2 -0
  143. package/dist/components/layout/scroll-area/scroll-area.utils.d.ts +2 -0
  144. package/dist/components/layout/scroll-area/scroll-area.utils.js +8 -0
  145. package/dist/components/layout/scroll-area/scroll-area.utils.js.map +1 -0
  146. package/dist/components/layout/section/index.cjs +10 -4
  147. package/dist/components/layout/section/index.cjs.map +1 -1
  148. package/dist/components/layout/section/index.d.cts +1 -1
  149. package/dist/components/layout/section/index.d.ts +1 -1
  150. package/dist/components/layout/section/index.js +11 -5
  151. package/dist/components/layout/section/index.js.map +1 -1
  152. package/dist/components/layout/section/section.css +9 -3
  153. package/dist/components/layout/section/types.d.cts +5 -5
  154. package/dist/components/layout/section/types.d.ts +5 -5
  155. package/dist/components/layout/separator/index.cjs +18 -0
  156. package/dist/components/layout/separator/index.cjs.map +1 -0
  157. package/dist/components/layout/separator/index.d.cts +17 -0
  158. package/dist/components/layout/separator/index.d.ts +17 -0
  159. package/dist/components/layout/separator/index.js +18 -0
  160. package/dist/components/layout/separator/index.js.map +1 -0
  161. package/dist/components/layout/separator/separator.css +15 -0
  162. package/dist/components/layout/separator/separator.utils.cjs +11 -0
  163. package/dist/components/layout/separator/separator.utils.cjs.map +1 -0
  164. package/dist/components/layout/separator/separator.utils.d.cts +2 -0
  165. package/dist/components/layout/separator/separator.utils.d.ts +2 -0
  166. package/dist/components/layout/separator/separator.utils.js +11 -0
  167. package/dist/components/layout/separator/separator.utils.js.map +1 -0
  168. package/dist/components/layout/stack/index.cjs +18 -2
  169. package/dist/components/layout/stack/index.cjs.map +1 -1
  170. package/dist/components/layout/stack/index.d.cts +8 -6
  171. package/dist/components/layout/stack/index.d.ts +8 -6
  172. package/dist/components/layout/stack/index.js +18 -2
  173. package/dist/components/layout/stack/index.js.map +1 -1
  174. package/dist/components/layout/stack/stack.css +118 -138
  175. package/dist/components/navigation/accordion/index.cjs.map +1 -1
  176. package/dist/components/navigation/accordion/index.js.map +1 -1
  177. package/dist/components/navigation/carousel/index.cjs +5 -2
  178. package/dist/components/navigation/carousel/index.cjs.map +1 -1
  179. package/dist/components/navigation/carousel/index.js +5 -2
  180. package/dist/components/navigation/carousel/index.js.map +1 -1
  181. package/dist/components/navigation/pagination/index.cjs +146 -0
  182. package/dist/components/navigation/pagination/index.cjs.map +1 -0
  183. package/dist/components/navigation/pagination/index.d.cts +3 -0
  184. package/dist/components/navigation/pagination/index.d.ts +3 -0
  185. package/dist/components/navigation/pagination/index.js +146 -0
  186. package/dist/components/navigation/pagination/index.js.map +1 -0
  187. package/dist/components/navigation/pagination/pagination.css +134 -0
  188. package/dist/components/navigation/pagination/pagination.types.d.cts +38 -0
  189. package/dist/components/navigation/pagination/pagination.types.d.ts +38 -0
  190. package/dist/components/navigation/pagination/pagination.utils.cjs +54 -0
  191. package/dist/components/navigation/pagination/pagination.utils.cjs.map +1 -0
  192. package/dist/components/navigation/pagination/pagination.utils.js +53 -0
  193. package/dist/components/navigation/pagination/pagination.utils.js.map +1 -0
  194. package/dist/components/navigation/tabs/index.d.cts +3 -2
  195. package/dist/components/navigation/tabs/index.d.ts +3 -2
  196. package/dist/components/navigation/tree-view/index.cjs.map +1 -1
  197. package/dist/components/navigation/tree-view/index.js.map +1 -1
  198. package/dist/components/overlays/context-menu/context-menu.css +151 -0
  199. package/dist/components/overlays/context-menu/context-menu.types.d.cts +69 -0
  200. package/dist/components/overlays/context-menu/context-menu.types.d.ts +69 -0
  201. package/dist/components/overlays/context-menu/context-menu.utils.cjs +46 -0
  202. package/dist/components/overlays/context-menu/context-menu.utils.cjs.map +1 -0
  203. package/dist/components/overlays/context-menu/context-menu.utils.js +40 -0
  204. package/dist/components/overlays/context-menu/context-menu.utils.js.map +1 -0
  205. package/dist/components/overlays/context-menu/index.cjs +830 -0
  206. package/dist/components/overlays/context-menu/index.cjs.map +1 -0
  207. package/dist/components/overlays/context-menu/index.d.cts +42 -0
  208. package/dist/components/overlays/context-menu/index.d.ts +42 -0
  209. package/dist/components/overlays/context-menu/index.js +818 -0
  210. package/dist/components/overlays/context-menu/index.js.map +1 -0
  211. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.cjs.map +1 -1
  212. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.js.map +1 -1
  213. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.cjs.map +1 -1
  214. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.js.map +1 -1
  215. package/dist/components/typography/heading.cjs +6 -2
  216. package/dist/components/typography/heading.cjs.map +1 -1
  217. package/dist/components/typography/heading.d.cts +3 -2
  218. package/dist/components/typography/heading.d.ts +3 -2
  219. package/dist/components/typography/heading.js +6 -2
  220. package/dist/components/typography/heading.js.map +1 -1
  221. package/dist/components/typography/text.cjs +6 -2
  222. package/dist/components/typography/text.cjs.map +1 -1
  223. package/dist/components/typography/text.d.cts +3 -2
  224. package/dist/components/typography/text.d.ts +3 -2
  225. package/dist/components/typography/text.js +6 -2
  226. package/dist/components/typography/text.js.map +1 -1
  227. package/dist/components/utilities/preview/index.cjs +89 -21
  228. package/dist/components/utilities/preview/index.cjs.map +1 -1
  229. package/dist/components/utilities/preview/index.d.cts +6 -2
  230. package/dist/components/utilities/preview/index.d.ts +6 -2
  231. package/dist/components/utilities/preview/index.js +89 -21
  232. package/dist/components/utilities/preview/index.js.map +1 -1
  233. package/dist/components/utilities/preview/preview.css +26 -11
  234. package/dist/components/utilities/transition/index.d.cts +1 -1
  235. package/dist/components/utilities/transition/index.d.ts +1 -1
  236. package/dist/index.cjs +136 -97
  237. package/dist/index.d.cts +23 -2
  238. package/dist/index.d.ts +23 -2
  239. package/dist/index.js +12 -1
  240. package/package.json +7 -6
package/README.md CHANGED
@@ -1,98 +1,98 @@
1
- # @puzzle-ui/ui
1
+ # Getting Started
2
2
 
3
- Composable React UI components for Puzzle: actions, forms, data display,
4
- layout, navigation, overlays, typography, and utilities.
3
+ Install Puzzle in your React app, build your first interface, and customize the theme.
5
4
 
6
- > Puzzle is under active development and is not ready for production use.
7
- > APIs, styling, accessibility coverage, and framework compatibility may
8
- > change. Use it for experimentation and evaluation.
5
+ > \[!WARNING\] **Puzzle is not ready for production use.**
6
+ >
7
+ > This project is under active development. APIs, component props,
8
+ > package exports, styling, and internal implementation may change
9
+ > without notice. Components may be incomplete, and testing,
10
+ > accessibility, documentation, and framework compatibility are not yet
11
+ > guaranteed. Use it for experimentation and evaluation only---not for
12
+ > production applications.
9
13
 
10
- ## Installation
14
+ Puzzle is a TypeScript and React UI component library built around reusable components and shared design tokens. Its components are composable and router-independent, with styling supplied by `"@puzzle-ui/theme`. The framework is setup to be compatible with `Next.js`, `Tanstack Start` and `react-router`.
11
15
 
12
- Install the UI library and its theme provider:
16
+ **Puzzle is under active development and is not ready for production use.** APIs, props, exports, and styling may change without notice. Accessibility and framework compatibility are still being tested. Use the project for experimentation and evaluation.
13
17
 
14
- ```sh
15
- npm install @puzzle-ui/ui @puzzle-ui/theme
16
- # or
17
- bun add @puzzle-ui/ui @puzzle-ui/theme
18
- # or
19
- pnpm add @puzzle-ui/ui @puzzle-ui/theme
20
- # or
21
- yarn add @puzzle-ui/ui @puzzle-ui/theme
22
- ```
18
+ ## Prerequisites
23
19
 
24
- Requires React and React DOM 19 (`^19.0.0`) and a bundler that supports CSS
25
- imports, such as Vite. Consumers do not need Bun.
20
+ - A package manager: npm, Bun, pnpm, or Yarn.
21
+ - An existing React application with a bundler that supports CSS imports, such as Vite.
22
+ - Familiarity with React and TypeScript. The UI and theme packages require React and React DOM 19 or later within the supported React 19 range.
26
23
 
27
- ## Usage
24
+ ## Set up a new project
28
25
 
29
- ```tsx
30
- import { Theme } from "@puzzle-ui/theme";
31
- import { Button } from "@puzzle-ui/ui";
26
+ Simple run our @puzzle-ui/create project template to get started.
32
27
 
33
- export const App = () => (
34
- <Theme>
35
- <main>
36
- <h1>Hello, Puzzle</h1>
37
- <Button onClick={() => window.alert("Hello!")}>
38
- Get started
39
- </Button>
40
- </main>
41
- </Theme>
42
- );
28
+ npm:
29
+
30
+ ```bash
31
+ npx @puzzle-ui/create
32
+ ```
33
+
34
+ bun:
35
+
36
+ ```bash
37
+ bunx @puzzle-ui/create
43
38
  ```
44
39
 
45
- `Theme` supplies the design tokens and global defaults. Component CSS is
46
- imported automatically; no separate Puzzle stylesheet or Tailwind setup is
47
- required. Customize colors, fonts, spacing, and other tokens through
48
- [`@puzzle-ui/theme`](../theme/README.md).
40
+ Puzzle can set up a new project for you with the following framework options:
49
41
 
50
- ## Components and imports
42
+ - Basic React app
43
+ - Tanstack start
44
+ - Next.js
51
45
 
52
- Use named imports from `@puzzle-ui/ui`. Components include buttons, cards,
53
- inputs, dialogs, tabs, navigation, layout primitives, and typography.
54
- Internal component paths are not exported package entry points.
46
+ Furthermore you can choose to install tailwindcss or not.
47
+ It directly installs all dependencies and sets up the project for you.
55
48
 
56
- Browse the repository's
57
- [component documentation](../../apps/site/content/docs/components/ui) for
58
- examples, props, and accessibility guidance. Interactive components need a
59
- client boundary in React Server Component applications.
49
+ ## Set up in an existing project:
60
50
 
61
- The package ships ESM and CommonJS builds with matching TypeScript
62
- declarations. Its CSS requires a CSS-aware bundler rather than bare Node.js.
63
- Test your chosen components in your framework; compatibility is still being
64
- evaluated.
51
+ Install the UI library and theme package in your application's directory. Choose your package manager below:
65
52
 
66
- ## Development
53
+ npm:
67
54
 
68
- From an installed repository checkout:
55
+ ```bash
56
+ npm install @puzzle-ui/ui --save
57
+ ```
58
+
59
+ bun:
69
60
 
70
- ```sh
71
- npm run build --workspace=@puzzle-ui/ui
61
+ ```bash
62
+ bun add @puzzle-ui/create
72
63
  ```
73
64
 
74
- `prepack` rebuilds the package before packing or publishing. See the root
75
- [publishing guide](../../README.md#publishing-packages).
65
+ pnpm:
76
66
 
77
- ## Tests
67
+ ```bash
68
+ pnpm add @puzzle-ui/ui
69
+ ```
78
70
 
79
- Three layers, selected by file name and run by Vitest projects (see `vitest.config.ts`):
71
+ yarn:
80
72
 
81
- | Layer | File pattern | Environment | Script |
82
- | --------- | --------------------- | ---------------- | ------------------------ |
83
- | Unit | `*.unit.test.ts` | Node, no DOM | `bun run test:unit` |
84
- | Component | `*.test.tsx` / `.ts` | jsdom | `bun run test:component` |
85
- | Browser | `*.browser.test.tsx` | Chromium (Playwright) | `bun run test:browser` |
73
+ ```bash
74
+ yarn add @puzzle-ui/ui
75
+ ```
86
76
 
87
- - **Unit**: pure logic (utilities, normalizers).
88
- - **Component**: rendering, ARIA and interaction with Testing Library.
89
- - **Browser**: behavior that needs real layout, computed styles, focus or pointer input.
77
+ These commands install published packages; they do not clone the repository or build its workspaces. Puzzle does not require Bun in your application. React and React DOM are peer dependencies and should already be installed in your app.
90
78
 
91
- `bun run vitest` runs unit and component; `bun run test:all` runs everything. The first browser run needs `bunx playwright install chromium`.
79
+ ## Your first interface
92
80
 
93
- Run these test commands from this package directory in a repository
94
- checkout, after installing workspace dependencies.
81
+ Import components from `"@puzzle-ui/ui` and wrap your application in `Theme` from `"@puzzle-ui/theme`:
95
82
 
96
- ## License
83
+ ```tsx
84
+ import { Theme } from "@puzzle-ui/theme";
85
+ import { Button } from "@puzzle-ui/ui";
97
86
 
98
- MIT. See [LICENSE](../../LICENSE); the published license is at `dist/LICENSE`.
87
+ export const App = () => (
88
+ <Theme>
89
+ <main>
90
+ <h1>Hello, Puzzle</h1>
91
+ <p>Build your interface with reusable components and shared tokens.</p>
92
+ <Button onClick={() => window.alert("Welcome to Puzzle!")}>
93
+ Get started
94
+ </Button>
95
+ </main>
96
+ </Theme>
97
+ );
98
+ ```
@@ -44,7 +44,7 @@
44
44
  }
45
45
 
46
46
  .puzzle-button--primary:hover:not(:disabled):not([aria-disabled="true"]) {
47
- filter: brightness(.93);
47
+ background: color-mix(in srgb, var(--puzzle-color-primary) 88%, var(--puzzle-color-text));
48
48
  }
49
49
 
50
50
  .puzzle-button--secondary {
@@ -53,7 +53,7 @@
53
53
  }
54
54
 
55
55
  .puzzle-button--secondary:hover:not(:disabled):not([aria-disabled="true"]) {
56
- filter: brightness(.96);
56
+ background: color-mix(in srgb, var(--puzzle-color-surface-sunken) 85%, var(--puzzle-color-text));
57
57
  }
58
58
 
59
59
  .puzzle-button--outline {
@@ -160,7 +160,10 @@
160
160
  }
161
161
 
162
162
  .puzzle-button__content {
163
+ gap: var(--puzzle-button-gap, var(--puzzle-space-2, .5rem));
164
+ flex-direction: row;
163
165
  flex: 0 auto;
166
+ display: inline-flex;
164
167
  }
165
168
 
166
169
  .puzzle-button__leading, .puzzle-button__trailing, .puzzle-button__spinner {
@@ -24,41 +24,40 @@
24
24
  }
25
25
 
26
26
  .puzzle-button-group--attached {
27
+ --puzzle-button-group-divider-color: var(--puzzle-color-border);
28
+ isolation: isolate;
27
29
  gap: 0;
28
30
  }
29
31
 
30
- .puzzle-button-group--attached > :not(:first-child) {
31
- margin-inline-start: -1px;
32
- }
33
-
34
- .puzzle-button-group--horizontal .puzzle-button-group--attached {
35
- border-radius: inherit;
32
+ .puzzle-button-group--attached > :is(:hover, :focus-visible) {
33
+ z-index: 1;
34
+ position: relative;
36
35
  }
37
36
 
38
- .puzzle-button-group--attached > :not(:first-child):not(:last-child) {
39
- border-radius: 0;
37
+ .puzzle-button-group--horizontal.puzzle-button-group--attached > :not(:first-child) {
38
+ border-inline-start: 1px solid var(--puzzle-button-group-divider-color);
39
+ border-start-start-radius: 0;
40
+ border-end-start-radius: 0;
41
+ margin-inline-start: -1px;
40
42
  }
41
43
 
42
- .puzzle-button-group--horizontal .puzzle-button-group--attached > :first-child {
44
+ .puzzle-button-group--horizontal.puzzle-button-group--attached > :not(:last-child) {
43
45
  border-start-end-radius: 0;
44
46
  border-end-end-radius: 0;
45
47
  }
46
48
 
47
- .puzzle-button-group--horizontal .puzzle-button-group--attached > :last-child {
49
+ .puzzle-button-group--vertical.puzzle-button-group--attached > :not(:first-child) {
50
+ border-block-start: 1px solid var(--puzzle-button-group-divider-color);
48
51
  border-start-start-radius: 0;
49
- border-end-start-radius: 0;
52
+ border-start-end-radius: 0;
53
+ margin-block-start: -1px;
50
54
  }
51
55
 
52
- .puzzle-button-group--vertical .puzzle-button-group--attached > :first-child {
56
+ .puzzle-button-group--vertical.puzzle-button-group--attached > :not(:last-child) {
53
57
  border-end-end-radius: 0;
54
58
  border-end-start-radius: 0;
55
59
  }
56
60
 
57
- .puzzle-button-group--vertical .puzzle-button-group--attached > :last-child {
58
- border-start-start-radius: 0;
59
- border-start-end-radius: 0;
60
- }
61
-
62
61
  .puzzle-button-group--disabled {
63
62
  cursor: not-allowed;
64
63
  }
@@ -1,22 +1,30 @@
1
1
  .puzzle-badge {
2
+ justify-content: center;
3
+ align-items: center;
2
4
  display: inline-flex;
3
5
  position: relative;
4
6
  }
5
7
 
6
8
  .puzzle-badge > .puzzle-badge-indicator {
7
- aspect-ratio: 1;
9
+ box-sizing: border-box;
10
+ padding: var(--puzzle-space-1) var(--puzzle-space-2);
8
11
  border-radius: var(--puzzle-radius-full, 50%);
9
12
  font-weight: var(--puzzle-font-weight-normal, 400);
10
13
  line-height: var(--puzzle-font-line-height-none, 1);
11
14
  text-align: center;
15
+ white-space: nowrap;
12
16
  vertical-align: middle;
13
17
  justify-content: center;
14
18
  align-items: center;
15
- padding: .25em;
16
19
  display: inline-flex;
17
20
  position: absolute;
18
21
  }
19
22
 
23
+ .puzzle-badge > .puzzle-badge-indicator--single {
24
+ padding-inline: var(--puzzle-space-1);
25
+ aspect-ratio: 1;
26
+ }
27
+
20
28
  .puzzle-badge-primary > .puzzle-badge-indicator {
21
29
  background-color: var(--puzzle-color-primary);
22
30
  color: var(--puzzle-color-primary-foreground);
@@ -89,3 +97,8 @@
89
97
  left: 85.3553%;
90
98
  transform: translate(-50%, -50%);
91
99
  }
100
+
101
+ .puzzle-badge.puzzle-badge-standalone > .puzzle-badge-indicator {
102
+ position: static;
103
+ transform: none;
104
+ }
@@ -6,19 +6,30 @@ let react_jsx_runtime = require("react/jsx-runtime");
6
6
  const Badge = ({ content, size = 20, color = "primary", anchorOrigin = {
7
7
  vertical: "top",
8
8
  horizontal: "right"
9
+ }, anchorOffset = {
10
+ vertical: 0,
11
+ horizontal: 0
9
12
  }, anchorOverlap = "rectangular", className, children }) => {
13
+ if (!Number.isFinite(anchorOffset.vertical) || !Number.isFinite(anchorOffset.horizontal)) throw new TypeError("Badge anchorOffset values must be finite numbers.");
10
14
  const resolvedSize = Math.max(size, 16);
11
15
  const isHex = (0, _puzzle_ui_core.isHexColor)(color);
12
16
  const isDark = isHex ? (0, _puzzle_ui_core.isDarkColor)(color) : false;
13
- const classes = (0, _puzzle_ui_core.cn)("puzzle-badge", anchorOrigin.vertical, anchorOrigin.horizontal, anchorOverlap, !isHex && `puzzle-badge-${color}`, className);
17
+ const textContent = typeof content === "string" || typeof content === "number" ? String(content).trim() : null;
18
+ const isSingleCharacter = textContent != null && Array.from(textContent).length === 1;
19
+ const classes = (0, _puzzle_ui_core.cn)("puzzle-badge", children != null && [
20
+ anchorOrigin.vertical,
21
+ anchorOrigin.horizontal,
22
+ anchorOverlap
23
+ ], children == null && "puzzle-badge-standalone", !isHex && `puzzle-badge-${color}`, className);
14
24
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
15
25
  className: classes,
16
26
  children: [children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17
- className: "puzzle-badge-indicator",
27
+ className: (0, _puzzle_ui_core.cn)("puzzle-badge-indicator", isSingleCharacter && "puzzle-badge-indicator--single"),
18
28
  style: {
19
29
  fontSize: `clamp(0.7rem, calc(${resolvedSize}px - 1em), 4rem)`,
20
30
  minHeight: `${resolvedSize}px`,
21
31
  minWidth: `${resolvedSize}px`,
32
+ translate: children != null ? `${anchorOffset.horizontal * (anchorOrigin.horizontal === "left" ? 1 : -1)}px ${anchorOffset.vertical * (anchorOrigin.vertical === "top" ? 1 : -1)}px` : void 0,
22
33
  backgroundColor: isHex ? color : void 0,
23
34
  color: isHex ? isDark ? "var(--puzzle-color-light-foreground)" : "var(--puzzle-color-dark-foreground)" : void 0
24
35
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["isHexColor","isDarkColor","cn"],"sources":["../../../../src/components/data-display/badge/index.tsx"],"sourcesContent":["import { cn, isDarkColor, isHexColor } from \"@puzzle-ui/core\";\nimport { type ReactNode } from \"react\";\nimport \"./badge.css\";\n\ntype AnchorOrigin = {\n vertical: \"top\" | \"bottom\";\n horizontal: \"left\" | \"right\";\n};\n\ntype AnchorOverlap = \"rectangular\" | \"circular\";\ntype BadgeColor =\n | \"primary\"\n | \"secondary\"\n | \"accent\"\n | \"danger\"\n | \"info\"\n | `#${string}`;\n\ntype BadgeProps = {\n content: ReactNode;\n size?: number;\n color?: BadgeColor;\n anchorOrigin?: AnchorOrigin;\n anchorOverlap?: AnchorOverlap;\n className?: string;\n children?: ReactNode;\n};\n\nconst Badge = ({\n content,\n size = 20,\n color = \"primary\",\n anchorOrigin = { vertical: \"top\", horizontal: \"right\" },\n anchorOverlap = \"rectangular\",\n className,\n children,\n}: BadgeProps) => {\n const resolvedSize = Math.max(size, 16);\n const isHex = isHexColor(color);\n const isDark = isHex ? isDarkColor(color) : false;\n\n const classes = cn(\n \"puzzle-badge\",\n anchorOrigin.vertical,\n anchorOrigin.horizontal,\n anchorOverlap,\n !isHex && `puzzle-badge-${color}`,\n className,\n );\n\n return (\n <div className={classes}>\n {children}\n <span\n className=\"puzzle-badge-indicator\"\n style={{\n fontSize: `clamp(0.7rem, calc(${resolvedSize}px - 1em), 4rem)`,\n minHeight: `${resolvedSize}px`,\n minWidth: `${resolvedSize}px`,\n backgroundColor: isHex ? color : undefined,\n color: isHex\n ? isDark\n ? \"var(--puzzle-color-light-foreground)\"\n : \"var(--puzzle-color-dark-foreground)\"\n : undefined,\n }}\n >\n {content}\n </span>\n </div>\n );\n};\n\nexport {\n Badge,\n type BadgeProps,\n type BadgeColor,\n type AnchorOrigin,\n type AnchorOverlap,\n};\n"],"mappings":";;;;;AA4BA,MAAM,SAAS,EACb,SACA,OAAO,IACP,QAAQ,WACR,eAAe;CAAE,UAAU;CAAO,YAAY;AAAQ,GACtD,gBAAgB,eAChB,WACA,eACgB;CAChB,MAAM,eAAe,KAAK,IAAI,MAAM,EAAE;CACtC,MAAM,SAAA,GAAQA,gBAAAA,WAAAA,CAAW,KAAK;CAC9B,MAAM,SAAS,SAAA,GAAQC,gBAAAA,YAAAA,CAAY,KAAK,IAAI;CAE5C,MAAM,WAAA,GAAUC,gBAAAA,GAAAA,CACd,gBACA,aAAa,UACb,aAAa,YACb,eACA,CAAC,SAAS,gBAAgB,SAC1B,SACF;CAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAW;EAAhB,UAAA,CACG,UACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GACE,WAAU;GACV,OAAO;IACL,UAAU,sBAAsB,aAAa;IAC7C,WAAW,GAAG,aAAa;IAC3B,UAAU,GAAG,aAAa;IAC1B,iBAAiB,QAAQ,QAAQ,KAAA;IACjC,OAAO,QACH,SACE,yCACA,wCACF,KAAA;GACN;GAEC,UAAA;EACG,CAAA,CACH;;AAET"}
1
+ {"version":3,"file":"index.cjs","names":["isHexColor","isDarkColor","cn"],"sources":["../../../../src/components/data-display/badge/index.tsx"],"sourcesContent":["import { cn, isDarkColor, isHexColor } from \"@puzzle-ui/core\";\nimport { type ReactNode } from \"react\";\nimport \"./badge.css\";\n\ntype AnchorOrigin = {\n vertical: \"top\" | \"bottom\";\n horizontal: \"left\" | \"right\";\n};\n\ntype AnchorOffset = {\n vertical: number;\n horizontal: number;\n};\n\ntype AnchorOverlap = \"rectangular\" | \"circular\";\ntype BadgeColor =\n | \"primary\"\n | \"secondary\"\n | \"accent\"\n | \"danger\"\n | \"info\"\n | `#${string}`;\n\ntype BadgeProps = {\n content: ReactNode;\n size?: number;\n color?: BadgeColor;\n anchorOrigin?: AnchorOrigin;\n anchorOffset?: AnchorOffset;\n anchorOverlap?: AnchorOverlap;\n className?: string;\n children?: ReactNode;\n};\n\nconst Badge = ({\n content,\n size = 20,\n color = \"primary\",\n anchorOrigin = { vertical: \"top\", horizontal: \"right\" },\n anchorOffset = { vertical: 0, horizontal: 0 },\n anchorOverlap = \"rectangular\",\n className,\n children,\n}: BadgeProps) => {\n if (!Number.isFinite(anchorOffset.vertical) || !Number.isFinite(anchorOffset.horizontal)) {\n throw new TypeError(\"Badge anchorOffset values must be finite numbers.\");\n }\n\n const resolvedSize = Math.max(size, 16);\n const isHex = isHexColor(color);\n const isDark = isHex ? isDarkColor(color) : false;\n\n const textContent =\n typeof content === \"string\" || typeof content === \"number\"\n ? String(content).trim()\n : null;\n const isSingleCharacter =\n textContent != null && Array.from(textContent).length === 1;\n\n const classes = cn(\n \"puzzle-badge\",\n children != null && [\n anchorOrigin.vertical,\n anchorOrigin.horizontal,\n anchorOverlap,\n ],\n children == null && \"puzzle-badge-standalone\",\n !isHex && `puzzle-badge-${color}`,\n className,\n );\n\n return (\n <div className={classes}>\n {children}\n <span\n className={cn(\n \"puzzle-badge-indicator\",\n isSingleCharacter && \"puzzle-badge-indicator--single\",\n )}\n style={{\n fontSize: `clamp(0.7rem, calc(${resolvedSize}px - 1em), 4rem)`,\n minHeight: `${resolvedSize}px`,\n minWidth: `${resolvedSize}px`,\n translate: children != null\n ? `${anchorOffset.horizontal * (anchorOrigin.horizontal === \"left\" ? 1 : -1)}px ${anchorOffset.vertical * (anchorOrigin.vertical === \"top\" ? 1 : -1)}px`\n : undefined,\n backgroundColor: isHex ? color : undefined,\n color: isHex\n ? isDark\n ? \"var(--puzzle-color-light-foreground)\"\n : \"var(--puzzle-color-dark-foreground)\"\n : undefined,\n }}\n >\n {content}\n </span>\n </div>\n );\n};\n\nexport {\n Badge,\n type BadgeProps,\n type BadgeColor,\n type AnchorOrigin,\n type AnchorOffset,\n type AnchorOverlap,\n};\n"],"mappings":";;;;;AAkCA,MAAM,SAAS,EACb,SACA,OAAO,IACP,QAAQ,WACR,eAAe;CAAE,UAAU;CAAO,YAAY;AAAQ,GACtD,eAAe;CAAE,UAAU;CAAG,YAAY;AAAE,GAC5C,gBAAgB,eAChB,WACA,eACgB;CAChB,IAAI,CAAC,OAAO,SAAS,aAAa,QAAQ,KAAK,CAAC,OAAO,SAAS,aAAa,UAAU,GACrF,MAAM,IAAI,UAAU,mDAAmD;CAGzE,MAAM,eAAe,KAAK,IAAI,MAAM,EAAE;CACtC,MAAM,SAAA,GAAQA,gBAAAA,WAAAA,CAAW,KAAK;CAC9B,MAAM,SAAS,SAAA,GAAQC,gBAAAA,YAAAA,CAAY,KAAK,IAAI;CAE5C,MAAM,cACJ,OAAO,YAAY,YAAY,OAAO,YAAY,WAC9C,OAAO,OAAO,CAAC,CAAC,KAAK,IACrB;CACN,MAAM,oBACJ,eAAe,QAAQ,MAAM,KAAK,WAAW,CAAC,CAAC,WAAW;CAE5D,MAAM,WAAA,GAAUC,gBAAAA,GAAAA,CACd,gBACA,YAAY,QAAQ;EAClB,aAAa;EACb,aAAa;EACb;CACF,GACA,YAAY,QAAQ,2BACpB,CAAC,SAAS,gBAAgB,SAC1B,SACF;CAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAW;EAAhB,UAAA,CACG,UACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GACE,YAAA,GAAWA,gBAAAA,GAAAA,CACT,0BACA,qBAAqB,gCACvB;GACA,OAAO;IACL,UAAU,sBAAsB,aAAa;IAC7C,WAAW,GAAG,aAAa;IAC3B,UAAU,GAAG,aAAa;IAC1B,WAAW,YAAY,OACnB,GAAG,aAAa,cAAc,aAAa,eAAe,SAAS,IAAI,IAAI,KAAK,aAAa,YAAY,aAAa,aAAa,QAAQ,IAAI,IAAI,MACnJ,KAAA;IACJ,iBAAiB,QAAQ,QAAQ,KAAA;IACjC,OAAO,QACH,SACE,yCACA,wCACF,KAAA;GACN;GAEC,UAAA;EACG,CAAA,CACH;;AAET"}
@@ -3,6 +3,10 @@ type AnchorOrigin = {
3
3
  vertical: "top" | "bottom";
4
4
  horizontal: "left" | "right";
5
5
  };
6
+ type AnchorOffset = {
7
+ vertical: number;
8
+ horizontal: number;
9
+ };
6
10
  type AnchorOverlap = "rectangular" | "circular";
7
11
  type BadgeColor = "primary" | "secondary" | "accent" | "danger" | "info" | `#${string}`;
8
12
  type BadgeProps = {
@@ -10,9 +14,10 @@ type BadgeProps = {
10
14
  size?: number;
11
15
  color?: BadgeColor;
12
16
  anchorOrigin?: AnchorOrigin;
17
+ anchorOffset?: AnchorOffset;
13
18
  anchorOverlap?: AnchorOverlap;
14
19
  className?: string;
15
20
  children?: ReactNode;
16
21
  };
17
- declare const Badge: ({ content, size, color, anchorOrigin, anchorOverlap, className, children }: BadgeProps) => import("react").JSX.Element;
18
- export { type AnchorOrigin, type AnchorOverlap, Badge, type BadgeColor, type BadgeProps };
22
+ declare const Badge: ({ content, size, color, anchorOrigin, anchorOffset, anchorOverlap, className, children }: BadgeProps) => import("react").JSX.Element;
23
+ export { type AnchorOffset, type AnchorOrigin, type AnchorOverlap, Badge, type BadgeColor, type BadgeProps };
@@ -3,6 +3,10 @@ type AnchorOrigin = {
3
3
  vertical: "top" | "bottom";
4
4
  horizontal: "left" | "right";
5
5
  };
6
+ type AnchorOffset = {
7
+ vertical: number;
8
+ horizontal: number;
9
+ };
6
10
  type AnchorOverlap = "rectangular" | "circular";
7
11
  type BadgeColor = "primary" | "secondary" | "accent" | "danger" | "info" | `#${string}`;
8
12
  type BadgeProps = {
@@ -10,9 +14,10 @@ type BadgeProps = {
10
14
  size?: number;
11
15
  color?: BadgeColor;
12
16
  anchorOrigin?: AnchorOrigin;
17
+ anchorOffset?: AnchorOffset;
13
18
  anchorOverlap?: AnchorOverlap;
14
19
  className?: string;
15
20
  children?: ReactNode;
16
21
  };
17
- declare const Badge: ({ content, size, color, anchorOrigin, anchorOverlap, className, children }: BadgeProps) => import("react").JSX.Element;
18
- export { type AnchorOrigin, type AnchorOverlap, Badge, type BadgeColor, type BadgeProps };
22
+ declare const Badge: ({ content, size, color, anchorOrigin, anchorOffset, anchorOverlap, className, children }: BadgeProps) => import("react").JSX.Element;
23
+ export { type AnchorOffset, type AnchorOrigin, type AnchorOverlap, Badge, type BadgeColor, type BadgeProps };
@@ -6,19 +6,30 @@ import { jsx, jsxs } from "react/jsx-runtime";
6
6
  const Badge = ({ content, size = 20, color = "primary", anchorOrigin = {
7
7
  vertical: "top",
8
8
  horizontal: "right"
9
+ }, anchorOffset = {
10
+ vertical: 0,
11
+ horizontal: 0
9
12
  }, anchorOverlap = "rectangular", className, children }) => {
13
+ if (!Number.isFinite(anchorOffset.vertical) || !Number.isFinite(anchorOffset.horizontal)) throw new TypeError("Badge anchorOffset values must be finite numbers.");
10
14
  const resolvedSize = Math.max(size, 16);
11
15
  const isHex = isHexColor(color);
12
16
  const isDark = isHex ? isDarkColor(color) : false;
13
- const classes = cn("puzzle-badge", anchorOrigin.vertical, anchorOrigin.horizontal, anchorOverlap, !isHex && `puzzle-badge-${color}`, className);
17
+ const textContent = typeof content === "string" || typeof content === "number" ? String(content).trim() : null;
18
+ const isSingleCharacter = textContent != null && Array.from(textContent).length === 1;
19
+ const classes = cn("puzzle-badge", children != null && [
20
+ anchorOrigin.vertical,
21
+ anchorOrigin.horizontal,
22
+ anchorOverlap
23
+ ], children == null && "puzzle-badge-standalone", !isHex && `puzzle-badge-${color}`, className);
14
24
  return /* @__PURE__ */ jsxs("div", {
15
25
  className: classes,
16
26
  children: [children, /* @__PURE__ */ jsx("span", {
17
- className: "puzzle-badge-indicator",
27
+ className: cn("puzzle-badge-indicator", isSingleCharacter && "puzzle-badge-indicator--single"),
18
28
  style: {
19
29
  fontSize: `clamp(0.7rem, calc(${resolvedSize}px - 1em), 4rem)`,
20
30
  minHeight: `${resolvedSize}px`,
21
31
  minWidth: `${resolvedSize}px`,
32
+ translate: children != null ? `${anchorOffset.horizontal * (anchorOrigin.horizontal === "left" ? 1 : -1)}px ${anchorOffset.vertical * (anchorOrigin.vertical === "top" ? 1 : -1)}px` : void 0,
22
33
  backgroundColor: isHex ? color : void 0,
23
34
  color: isHex ? isDark ? "var(--puzzle-color-light-foreground)" : "var(--puzzle-color-dark-foreground)" : void 0
24
35
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/data-display/badge/index.tsx"],"sourcesContent":["import { cn, isDarkColor, isHexColor } from \"@puzzle-ui/core\";\nimport { type ReactNode } from \"react\";\nimport \"./badge.css\";\n\ntype AnchorOrigin = {\n vertical: \"top\" | \"bottom\";\n horizontal: \"left\" | \"right\";\n};\n\ntype AnchorOverlap = \"rectangular\" | \"circular\";\ntype BadgeColor =\n | \"primary\"\n | \"secondary\"\n | \"accent\"\n | \"danger\"\n | \"info\"\n | `#${string}`;\n\ntype BadgeProps = {\n content: ReactNode;\n size?: number;\n color?: BadgeColor;\n anchorOrigin?: AnchorOrigin;\n anchorOverlap?: AnchorOverlap;\n className?: string;\n children?: ReactNode;\n};\n\nconst Badge = ({\n content,\n size = 20,\n color = \"primary\",\n anchorOrigin = { vertical: \"top\", horizontal: \"right\" },\n anchorOverlap = \"rectangular\",\n className,\n children,\n}: BadgeProps) => {\n const resolvedSize = Math.max(size, 16);\n const isHex = isHexColor(color);\n const isDark = isHex ? isDarkColor(color) : false;\n\n const classes = cn(\n \"puzzle-badge\",\n anchorOrigin.vertical,\n anchorOrigin.horizontal,\n anchorOverlap,\n !isHex && `puzzle-badge-${color}`,\n className,\n );\n\n return (\n <div className={classes}>\n {children}\n <span\n className=\"puzzle-badge-indicator\"\n style={{\n fontSize: `clamp(0.7rem, calc(${resolvedSize}px - 1em), 4rem)`,\n minHeight: `${resolvedSize}px`,\n minWidth: `${resolvedSize}px`,\n backgroundColor: isHex ? color : undefined,\n color: isHex\n ? isDark\n ? \"var(--puzzle-color-light-foreground)\"\n : \"var(--puzzle-color-dark-foreground)\"\n : undefined,\n }}\n >\n {content}\n </span>\n </div>\n );\n};\n\nexport {\n Badge,\n type BadgeProps,\n type BadgeColor,\n type AnchorOrigin,\n type AnchorOverlap,\n};\n"],"mappings":";;;;;AA4BA,MAAM,SAAS,EACb,SACA,OAAO,IACP,QAAQ,WACR,eAAe;CAAE,UAAU;CAAO,YAAY;AAAQ,GACtD,gBAAgB,eAChB,WACA,eACgB;CAChB,MAAM,eAAe,KAAK,IAAI,MAAM,EAAE;CACtC,MAAM,QAAQ,WAAW,KAAK;CAC9B,MAAM,SAAS,QAAQ,YAAY,KAAK,IAAI;CAE5C,MAAM,UAAU,GACd,gBACA,aAAa,UACb,aAAa,YACb,eACA,CAAC,SAAS,gBAAgB,SAC1B,SACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAW;EAAhB,UAAA,CACG,UACD,oBAAC,QAAD;GACE,WAAU;GACV,OAAO;IACL,UAAU,sBAAsB,aAAa;IAC7C,WAAW,GAAG,aAAa;IAC3B,UAAU,GAAG,aAAa;IAC1B,iBAAiB,QAAQ,QAAQ,KAAA;IACjC,OAAO,QACH,SACE,yCACA,wCACF,KAAA;GACN;GAEC,UAAA;EACG,CAAA,CACH;;AAET"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/data-display/badge/index.tsx"],"sourcesContent":["import { cn, isDarkColor, isHexColor } from \"@puzzle-ui/core\";\nimport { type ReactNode } from \"react\";\nimport \"./badge.css\";\n\ntype AnchorOrigin = {\n vertical: \"top\" | \"bottom\";\n horizontal: \"left\" | \"right\";\n};\n\ntype AnchorOffset = {\n vertical: number;\n horizontal: number;\n};\n\ntype AnchorOverlap = \"rectangular\" | \"circular\";\ntype BadgeColor =\n | \"primary\"\n | \"secondary\"\n | \"accent\"\n | \"danger\"\n | \"info\"\n | `#${string}`;\n\ntype BadgeProps = {\n content: ReactNode;\n size?: number;\n color?: BadgeColor;\n anchorOrigin?: AnchorOrigin;\n anchorOffset?: AnchorOffset;\n anchorOverlap?: AnchorOverlap;\n className?: string;\n children?: ReactNode;\n};\n\nconst Badge = ({\n content,\n size = 20,\n color = \"primary\",\n anchorOrigin = { vertical: \"top\", horizontal: \"right\" },\n anchorOffset = { vertical: 0, horizontal: 0 },\n anchorOverlap = \"rectangular\",\n className,\n children,\n}: BadgeProps) => {\n if (!Number.isFinite(anchorOffset.vertical) || !Number.isFinite(anchorOffset.horizontal)) {\n throw new TypeError(\"Badge anchorOffset values must be finite numbers.\");\n }\n\n const resolvedSize = Math.max(size, 16);\n const isHex = isHexColor(color);\n const isDark = isHex ? isDarkColor(color) : false;\n\n const textContent =\n typeof content === \"string\" || typeof content === \"number\"\n ? String(content).trim()\n : null;\n const isSingleCharacter =\n textContent != null && Array.from(textContent).length === 1;\n\n const classes = cn(\n \"puzzle-badge\",\n children != null && [\n anchorOrigin.vertical,\n anchorOrigin.horizontal,\n anchorOverlap,\n ],\n children == null && \"puzzle-badge-standalone\",\n !isHex && `puzzle-badge-${color}`,\n className,\n );\n\n return (\n <div className={classes}>\n {children}\n <span\n className={cn(\n \"puzzle-badge-indicator\",\n isSingleCharacter && \"puzzle-badge-indicator--single\",\n )}\n style={{\n fontSize: `clamp(0.7rem, calc(${resolvedSize}px - 1em), 4rem)`,\n minHeight: `${resolvedSize}px`,\n minWidth: `${resolvedSize}px`,\n translate: children != null\n ? `${anchorOffset.horizontal * (anchorOrigin.horizontal === \"left\" ? 1 : -1)}px ${anchorOffset.vertical * (anchorOrigin.vertical === \"top\" ? 1 : -1)}px`\n : undefined,\n backgroundColor: isHex ? color : undefined,\n color: isHex\n ? isDark\n ? \"var(--puzzle-color-light-foreground)\"\n : \"var(--puzzle-color-dark-foreground)\"\n : undefined,\n }}\n >\n {content}\n </span>\n </div>\n );\n};\n\nexport {\n Badge,\n type BadgeProps,\n type BadgeColor,\n type AnchorOrigin,\n type AnchorOffset,\n type AnchorOverlap,\n};\n"],"mappings":";;;;;AAkCA,MAAM,SAAS,EACb,SACA,OAAO,IACP,QAAQ,WACR,eAAe;CAAE,UAAU;CAAO,YAAY;AAAQ,GACtD,eAAe;CAAE,UAAU;CAAG,YAAY;AAAE,GAC5C,gBAAgB,eAChB,WACA,eACgB;CAChB,IAAI,CAAC,OAAO,SAAS,aAAa,QAAQ,KAAK,CAAC,OAAO,SAAS,aAAa,UAAU,GACrF,MAAM,IAAI,UAAU,mDAAmD;CAGzE,MAAM,eAAe,KAAK,IAAI,MAAM,EAAE;CACtC,MAAM,QAAQ,WAAW,KAAK;CAC9B,MAAM,SAAS,QAAQ,YAAY,KAAK,IAAI;CAE5C,MAAM,cACJ,OAAO,YAAY,YAAY,OAAO,YAAY,WAC9C,OAAO,OAAO,CAAC,CAAC,KAAK,IACrB;CACN,MAAM,oBACJ,eAAe,QAAQ,MAAM,KAAK,WAAW,CAAC,CAAC,WAAW;CAE5D,MAAM,UAAU,GACd,gBACA,YAAY,QAAQ;EAClB,aAAa;EACb,aAAa;EACb;CACF,GACA,YAAY,QAAQ,2BACpB,CAAC,SAAS,gBAAgB,SAC1B,SACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAW;EAAhB,UAAA,CACG,UACD,oBAAC,QAAD;GACE,WAAW,GACT,0BACA,qBAAqB,gCACvB;GACA,OAAO;IACL,UAAU,sBAAsB,aAAa;IAC7C,WAAW,GAAG,aAAa;IAC3B,UAAU,GAAG,aAAa;IAC1B,WAAW,YAAY,OACnB,GAAG,aAAa,cAAc,aAAa,eAAe,SAAS,IAAI,IAAI,KAAK,aAAa,YAAY,aAAa,aAAa,QAAQ,IAAI,IAAI,MACnJ,KAAA;IACJ,iBAAiB,QAAQ,QAAQ,KAAA;IACjC,OAAO,QACH,SACE,yCACA,wCACF,KAAA;GACN;GAEC,UAAA;EACG,CAAA,CACH;;AAET"}
@@ -0,0 +1,128 @@
1
+ .puzzle-empty-state {
2
+ --empty-state-padding: var(--puzzle-space-6, 1.5rem);
3
+ --empty-state-gap: var(--puzzle-space-3, .75rem);
4
+ box-sizing: border-box;
5
+ justify-content: center;
6
+ align-items: center;
7
+ gap: var(--empty-state-gap);
8
+ width: 100%;
9
+ min-width: 0;
10
+ padding: var(--empty-state-padding);
11
+ color: var(--puzzle-color-text);
12
+ font-family: var(--puzzle-font-family-body, inherit);
13
+ text-align: center;
14
+ border-radius: var(--puzzle-radius-lg, .75rem);
15
+ border: 1px solid #0000;
16
+ flex-direction: column;
17
+ display: flex;
18
+ }
19
+
20
+ .puzzle-empty-state--sm {
21
+ --empty-state-padding: var(--puzzle-space-4, 1rem);
22
+ --empty-state-gap: var(--puzzle-space-2, .5rem);
23
+ }
24
+
25
+ .puzzle-empty-state--md {
26
+ --empty-state-padding: var(--puzzle-space-6, 1.5rem);
27
+ --empty-state-gap: var(--puzzle-space-3, .75rem);
28
+ }
29
+
30
+ .puzzle-empty-state--lg {
31
+ --empty-state-padding: var(--puzzle-space-8, 2rem);
32
+ --empty-state-gap: var(--puzzle-space-4, 1rem);
33
+ border-radius: var(--puzzle-radius-xl, 1rem);
34
+ }
35
+
36
+ .puzzle-empty-state--default {
37
+ background: none;
38
+ }
39
+
40
+ .puzzle-empty-state--outlined {
41
+ border-style: dashed;
42
+ border-color: var(--puzzle-color-border);
43
+ }
44
+
45
+ .puzzle-empty-state--filled {
46
+ background: var(--puzzle-color-surface-sunken);
47
+ }
48
+
49
+ .puzzle-empty-state__header {
50
+ align-items: center;
51
+ gap: var(--puzzle-space-2, .5rem);
52
+ flex-direction: column;
53
+ width: 100%;
54
+ min-width: 0;
55
+ display: flex;
56
+ }
57
+
58
+ .puzzle-empty-state__media {
59
+ color: var(--puzzle-color-text-muted);
60
+ flex-shrink: 0;
61
+ justify-content: center;
62
+ align-items: center;
63
+ display: flex;
64
+ }
65
+
66
+ .puzzle-empty-state__media--icon {
67
+ border-radius: var(--puzzle-radius-lg, .75rem);
68
+ background: var(--puzzle-color-surface-sunken);
69
+ width: 3rem;
70
+ height: 3rem;
71
+ color: var(--puzzle-color-text-muted);
72
+ }
73
+
74
+ .puzzle-empty-state--lg .puzzle-empty-state__media--icon {
75
+ width: 3.5rem;
76
+ height: 3.5rem;
77
+ }
78
+
79
+ .puzzle-empty-state__media > svg {
80
+ flex-shrink: 0;
81
+ width: 1.5rem;
82
+ height: 1.5rem;
83
+ display: block;
84
+ }
85
+
86
+ .puzzle-empty-state__title {
87
+ color: var(--puzzle-color-text);
88
+ font-size: var(--puzzle-font-size-lg, 1.125rem);
89
+ font-weight: var(--puzzle-font-weight-semibold, 600);
90
+ line-height: var(--puzzle-font-line-height-tight, 1.25);
91
+ margin: 0;
92
+ }
93
+
94
+ .puzzle-empty-state--sm .puzzle-empty-state__title {
95
+ font-size: var(--puzzle-font-size-base, 1rem);
96
+ }
97
+
98
+ .puzzle-empty-state--lg .puzzle-empty-state__title {
99
+ font-size: var(--puzzle-font-size-lg, 1.125rem);
100
+ }
101
+
102
+ .puzzle-empty-state__description {
103
+ max-width: 36rem;
104
+ color: var(--puzzle-color-text-muted);
105
+ font-size: var(--puzzle-font-size-sm, .875rem);
106
+ line-height: var(--puzzle-font-line-height-normal, 1.5);
107
+ margin: 0;
108
+ }
109
+
110
+ .puzzle-empty-state__content {
111
+ justify-content: center;
112
+ align-items: center;
113
+ gap: var(--puzzle-space-2, .5rem);
114
+ flex-wrap: wrap;
115
+ width: 100%;
116
+ min-width: 0;
117
+ display: flex;
118
+ }
119
+
120
+ @media (width <= 30rem) {
121
+ .puzzle-empty-state__content {
122
+ flex-direction: column;
123
+ }
124
+
125
+ .puzzle-empty-state__content > * {
126
+ max-width: 100%;
127
+ }
128
+ }
@@ -0,0 +1,6 @@
1
+ let _puzzle_ui_core = require("@puzzle-ui/core");
2
+ // src/components/data-display/empty-state/empty-state.utils.ts
3
+ const getEmptyStateClasses = (size, variant, className) => (0, _puzzle_ui_core.cn)("puzzle-empty-state", `puzzle-empty-state--${size}`, `puzzle-empty-state--${variant}`, className);
4
+ exports.getEmptyStateClasses = getEmptyStateClasses;
5
+
6
+ //# sourceMappingURL=empty-state.utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state.utils.cjs","names":["cn"],"sources":["../../../../src/components/data-display/empty-state/empty-state.utils.ts"],"sourcesContent":["import { cn } from \"@puzzle-ui/core\";\n\ntype EmptyStateSize = \"sm\" | \"md\" | \"lg\";\ntype EmptyStateVariant = \"default\" | \"outlined\" | \"filled\";\n\nconst getEmptyStateClasses = (\n size: EmptyStateSize,\n variant: EmptyStateVariant,\n className?: string,\n) =>\n cn(\n \"puzzle-empty-state\",\n `puzzle-empty-state--${size}`,\n `puzzle-empty-state--${variant}`,\n className,\n );\n\nexport { getEmptyStateClasses };\n"],"mappings":";;AAKA,MAAM,wBACJ,MACA,SACA,eAAA,GAEAA,gBAAAA,GAAAA,CACE,sBACA,uBAAuB,QACvB,uBAAuB,WACvB,SACF"}
@@ -0,0 +1,6 @@
1
+ import { cn } from "@puzzle-ui/core";
2
+ // src/components/data-display/empty-state/empty-state.utils.ts
3
+ const getEmptyStateClasses = (size, variant, className) => cn("puzzle-empty-state", `puzzle-empty-state--${size}`, `puzzle-empty-state--${variant}`, className);
4
+ export { getEmptyStateClasses };
5
+
6
+ //# sourceMappingURL=empty-state.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state.utils.js","names":[],"sources":["../../../../src/components/data-display/empty-state/empty-state.utils.ts"],"sourcesContent":["import { cn } from \"@puzzle-ui/core\";\n\ntype EmptyStateSize = \"sm\" | \"md\" | \"lg\";\ntype EmptyStateVariant = \"default\" | \"outlined\" | \"filled\";\n\nconst getEmptyStateClasses = (\n size: EmptyStateSize,\n variant: EmptyStateVariant,\n className?: string,\n) =>\n cn(\n \"puzzle-empty-state\",\n `puzzle-empty-state--${size}`,\n `puzzle-empty-state--${variant}`,\n className,\n );\n\nexport { getEmptyStateClasses };\n"],"mappings":";;AAKA,MAAM,wBACJ,MACA,SACA,cAEA,GACE,sBACA,uBAAuB,QACvB,uBAAuB,WACvB,SACF"}