@owlmeans/web-panel 0.1.18-rc.4 → 0.1.18-rc.40

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 (208) hide show
  1. package/README.md +88 -27
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/web-panel/SKILL.md +349 -8
  4. package/build/@/components/ui/alert.js +1 -1
  5. package/build/@/components/ui/alert.js.map +1 -1
  6. package/build/@/components/ui/button.js +1 -1
  7. package/build/@/components/ui/button.js.map +1 -1
  8. package/build/@/components/ui/card.js +1 -1
  9. package/build/@/components/ui/card.js.map +1 -1
  10. package/build/@/components/ui/input.js +1 -1
  11. package/build/@/components/ui/input.js.map +1 -1
  12. package/build/@/components/ui/label.js +1 -1
  13. package/build/@/components/ui/label.js.map +1 -1
  14. package/build/@/components/ui/navigation-menu.d.ts +15 -0
  15. package/build/@/components/ui/navigation-menu.d.ts.map +1 -0
  16. package/build/@/components/ui/navigation-menu.js +32 -0
  17. package/build/@/components/ui/navigation-menu.js.map +1 -0
  18. package/build/@/components/ui/progress.js +1 -1
  19. package/build/@/components/ui/progress.js.map +1 -1
  20. package/build/@/components/ui/separator.js +1 -1
  21. package/build/@/components/ui/separator.js.map +1 -1
  22. package/build/auth/context.d.ts.map +1 -1
  23. package/build/auth/context.js +0 -1
  24. package/build/auth/context.js.map +1 -1
  25. package/build/auth/entrypoints.d.ts +10 -0
  26. package/build/auth/entrypoints.d.ts.map +1 -0
  27. package/build/auth/entrypoints.js +4 -0
  28. package/build/auth/entrypoints.js.map +1 -0
  29. package/build/auth/exports.d.ts +3 -3
  30. package/build/auth/exports.d.ts.map +1 -1
  31. package/build/auth/exports.js +3 -3
  32. package/build/auth/exports.js.map +1 -1
  33. package/build/auth/plugins/basic-ed25519.js +4 -4
  34. package/build/auth/plugins/basic-ed25519.js.map +1 -1
  35. package/build/auth/plugins/re-captcha.js +3 -3
  36. package/build/auth/plugins/re-captcha.js.map +1 -1
  37. package/build/auth/plugins/tunnel-consumer.js +1 -1
  38. package/build/auth/plugins/tunnel-consumer.js.map +1 -1
  39. package/build/components/block.js +2 -2
  40. package/build/components/block.js.map +1 -1
  41. package/build/components/footer/component.d.ts +12 -0
  42. package/build/components/footer/component.d.ts.map +1 -0
  43. package/build/components/footer/component.js +24 -0
  44. package/build/components/footer/component.js.map +1 -0
  45. package/build/components/footer/index.d.ts +3 -0
  46. package/build/components/footer/index.d.ts.map +1 -0
  47. package/build/components/footer/index.js +2 -0
  48. package/build/components/footer/index.js.map +1 -0
  49. package/build/components/footer/types.d.ts +11 -0
  50. package/build/components/footer/types.d.ts.map +1 -0
  51. package/build/components/footer/types.js +2 -0
  52. package/build/components/footer/types.js.map +1 -0
  53. package/build/components/form/button/component.js +2 -2
  54. package/build/components/form/button/component.js.map +1 -1
  55. package/build/components/form/component.js +2 -2
  56. package/build/components/form/component.js.map +1 -1
  57. package/build/components/form/text/component.js +2 -2
  58. package/build/components/form/text/component.js.map +1 -1
  59. package/build/components/index.d.ts +4 -0
  60. package/build/components/index.d.ts.map +1 -1
  61. package/build/components/index.js +4 -0
  62. package/build/components/index.js.map +1 -1
  63. package/build/components/link.js +3 -3
  64. package/build/components/link.js.map +1 -1
  65. package/build/components/login/append.d.ts +22 -0
  66. package/build/components/login/append.d.ts.map +1 -0
  67. package/build/components/login/append.js +21 -0
  68. package/build/components/login/append.js.map +1 -0
  69. package/build/components/login/credit.d.ts +17 -0
  70. package/build/components/login/credit.d.ts.map +1 -0
  71. package/build/components/login/credit.js +17 -0
  72. package/build/components/login/credit.js.map +1 -0
  73. package/build/components/login/icons.d.ts +14 -0
  74. package/build/components/login/icons.d.ts.map +1 -0
  75. package/build/components/login/icons.js +29 -0
  76. package/build/components/login/icons.js.map +1 -0
  77. package/build/components/login/index.d.ts +6 -0
  78. package/build/components/login/index.d.ts.map +1 -0
  79. package/build/components/login/index.js +6 -0
  80. package/build/components/login/index.js.map +1 -0
  81. package/build/components/login/screen.d.ts +23 -0
  82. package/build/components/login/screen.d.ts.map +1 -0
  83. package/build/components/login/screen.js +73 -0
  84. package/build/components/login/screen.js.map +1 -0
  85. package/build/components/login/terms.d.ts +9 -0
  86. package/build/components/login/terms.d.ts.map +1 -0
  87. package/build/components/login/terms.js +33 -0
  88. package/build/components/login/terms.js.map +1 -0
  89. package/build/components/nav/index.d.ts +5 -0
  90. package/build/components/nav/index.d.ts.map +1 -0
  91. package/build/components/nav/index.js +4 -0
  92. package/build/components/nav/index.js.map +1 -0
  93. package/build/components/nav/layout.d.ts +12 -0
  94. package/build/components/nav/layout.d.ts.map +1 -0
  95. package/build/components/nav/layout.js +40 -0
  96. package/build/components/nav/layout.js.map +1 -0
  97. package/build/components/nav/side.d.ts +11 -0
  98. package/build/components/nav/side.d.ts.map +1 -0
  99. package/build/components/nav/side.js +25 -0
  100. package/build/components/nav/side.js.map +1 -0
  101. package/build/components/nav/top.d.ts +10 -0
  102. package/build/components/nav/top.d.ts.map +1 -0
  103. package/build/components/nav/top.js +44 -0
  104. package/build/components/nav/top.js.map +1 -0
  105. package/build/components/nav/types.d.ts +55 -0
  106. package/build/components/nav/types.d.ts.map +1 -0
  107. package/build/components/nav/types.js +2 -0
  108. package/build/components/nav/types.js.map +1 -0
  109. package/build/components/panel-app/component.js +1 -1
  110. package/build/components/panel-app/component.js.map +1 -1
  111. package/build/components/status.js +1 -1
  112. package/build/components/status.js.map +1 -1
  113. package/build/components/text.js +1 -1
  114. package/build/components/text.js.map +1 -1
  115. package/build/components/toaster.d.ts +16 -0
  116. package/build/components/toaster.d.ts.map +1 -0
  117. package/build/components/toaster.js +52 -0
  118. package/build/components/toaster.js.map +1 -0
  119. package/build/components/uploader/image.js +1 -1
  120. package/build/components/uploader/image.js.map +1 -1
  121. package/build/consent/component.d.ts +11 -0
  122. package/build/consent/component.d.ts.map +1 -0
  123. package/build/consent/component.js +53 -0
  124. package/build/consent/component.js.map +1 -0
  125. package/build/consent/index.d.ts +4 -0
  126. package/build/consent/index.d.ts.map +1 -0
  127. package/build/consent/index.js +3 -0
  128. package/build/consent/index.js.map +1 -0
  129. package/build/context.d.ts.map +1 -1
  130. package/build/context.js +4 -0
  131. package/build/context.js.map +1 -1
  132. package/build/entrypoints.d.ts +8 -0
  133. package/build/entrypoints.d.ts.map +1 -0
  134. package/build/entrypoints.js +4 -0
  135. package/build/entrypoints.js.map +1 -0
  136. package/build/exports.d.ts +3 -4
  137. package/build/exports.d.ts.map +1 -1
  138. package/build/exports.js +3 -4
  139. package/build/exports.js.map +1 -1
  140. package/build/index.d.ts +1 -1
  141. package/build/index.d.ts.map +1 -1
  142. package/build/index.js +1 -1
  143. package/build/index.js.map +1 -1
  144. package/package.json +44 -33
  145. package/src/@/components/ui/alert.tsx +1 -1
  146. package/src/@/components/ui/button.tsx +1 -1
  147. package/src/@/components/ui/card.tsx +1 -1
  148. package/src/@/components/ui/input.tsx +1 -1
  149. package/src/@/components/ui/label.tsx +1 -1
  150. package/src/@/components/ui/navigation-menu.tsx +169 -0
  151. package/src/@/components/ui/progress.tsx +1 -1
  152. package/src/@/components/ui/separator.tsx +1 -1
  153. package/src/auth/context.ts +0 -2
  154. package/src/auth/entrypoints.ts +5 -0
  155. package/src/auth/exports.ts +3 -3
  156. package/src/auth/plugins/basic-ed25519.tsx +4 -4
  157. package/src/auth/plugins/re-captcha.tsx +3 -3
  158. package/src/auth/plugins/tunnel-consumer.tsx +1 -1
  159. package/src/components/block.tsx +2 -2
  160. package/src/components/footer/component.tsx +37 -0
  161. package/src/components/footer/index.ts +3 -0
  162. package/src/components/footer/types.ts +11 -0
  163. package/src/components/form/button/component.tsx +2 -2
  164. package/src/components/form/component.tsx +2 -2
  165. package/src/components/form/text/component.tsx +2 -2
  166. package/src/components/index.ts +4 -0
  167. package/src/components/link.tsx +3 -3
  168. package/src/components/login/append.ts +34 -0
  169. package/src/components/login/credit.tsx +34 -0
  170. package/src/components/login/icons.tsx +39 -0
  171. package/src/components/login/index.ts +5 -0
  172. package/src/components/login/screen.tsx +140 -0
  173. package/src/components/login/terms.tsx +74 -0
  174. package/src/components/nav/index.ts +5 -0
  175. package/src/components/nav/layout.tsx +85 -0
  176. package/src/components/nav/side.tsx +52 -0
  177. package/src/components/nav/top.tsx +62 -0
  178. package/src/components/nav/types.ts +56 -0
  179. package/src/components/panel-app/component.tsx +1 -1
  180. package/src/components/status.tsx +1 -1
  181. package/src/components/text.tsx +1 -1
  182. package/src/components/toaster.tsx +68 -0
  183. package/src/components/uploader/image.tsx +1 -1
  184. package/src/consent/component.tsx +62 -0
  185. package/src/consent/index.ts +11 -0
  186. package/src/context.ts +5 -0
  187. package/src/entrypoints.ts +5 -0
  188. package/src/exports.ts +3 -4
  189. package/src/index.ts +1 -1
  190. package/tests/context.ts +43 -0
  191. package/tests/harness/index.html +11 -0
  192. package/tests/harness/mount.tsx +195 -0
  193. package/tests/login.spec.ts +188 -0
  194. package/tests/nav.spec.ts +252 -0
  195. package/tests/package-boundary.spec.ts +19 -0
  196. package/tests/smoke.spec.ts +5 -1
  197. package/tests/toaster.spec.ts +59 -0
  198. package/build/.gitkeep +0 -0
  199. package/build/auth/modules.d.ts +0 -2
  200. package/build/auth/modules.d.ts.map +0 -1
  201. package/build/auth/modules.js +0 -4
  202. package/build/auth/modules.js.map +0 -1
  203. package/build/modules.d.ts +0 -2
  204. package/build/modules.d.ts.map +0 -1
  205. package/build/modules.js +0 -4
  206. package/build/modules.js.map +0 -1
  207. package/src/auth/modules.ts +0 -5
  208. package/src/modules.ts +0 -5
package/README.md CHANGED
@@ -6,7 +6,7 @@ instead of Material UI.
6
6
 
7
7
  ## When to use this package
8
8
 
9
- - New OwlMeans web apps where the consumer owns its shadcn primitives and
9
+ - New OwlMeans web apps using the package's shipped shadcn primitives and a
10
10
  Tailwind v4 theme.
11
11
  - Drop-in replacement for the previous Material-UI based `@owlmeans/web-panel`
12
12
  (which has been renamed to [`@owlmeans/mui-panel`](../mui-panel) for
@@ -15,7 +15,7 @@ instead of Material UI.
15
15
  ## Install
16
16
 
17
17
  ```sh
18
- bun add @owlmeans/web-panel
18
+ bun add @owlmeans/web-panel@^0.1.18-rc.31
19
19
  ```
20
20
 
21
21
  Peer requirements (the consuming app provides these): `react`, `react-dom`,
@@ -23,26 +23,14 @@ Peer requirements (the consuming app provides these): `react`, `react-dom`,
23
23
  `tailwind-merge`, `class-variance-authority`, plus the radix primitives
24
24
  listed in `peerDependencies`.
25
25
 
26
- ## Consumer setup — the `@` contract
26
+ ## Consumer setup — package boundary
27
27
 
28
- This package imports its shadcn primitives as `@/components/ui/<name>` and
29
- its utility as `@/lib/utils`. Build emits these specifiers verbatim
30
- (TypeScript `moduleResolution: Bundler`). The consumer's bundler must
31
- resolve `@/*` to its own shadcn primitive copy.
28
+ The package ships its shadcn primitives and `cn` helper as private implementation files. Its build
29
+ uses relative imports into that private tree, so a consumer needs neither an `@` bundler alias nor
30
+ a matching copy of the primitives. The consumer supplies the declared React, Tailwind and Radix peer
31
+ dependencies and may use its own unrelated shadcn setup.
32
32
 
33
- ### 1. Add the package's primitives to your app
34
-
35
- Generate the matching primitives in your app once. You can either copy them
36
- from this package's `src/@/components/ui/` or use the shadcn CLI:
37
-
38
- ```sh
39
- npx shadcn add button card input label progress alert separator
40
- ```
41
-
42
- This package was authored against the shadcn `new-york` style with
43
- `baseColor: neutral`. See `components.json` for the exact config.
44
-
45
- ### 2. Add Tailwind v4 theme tokens
33
+ ### 1. Add Tailwind v4 theme tokens
46
34
 
47
35
  The components rely on the following CSS variables (defined inside
48
36
  `@theme` in your app's globals.css):
@@ -62,13 +50,85 @@ The components rely on the following CSS variables (defined inside
62
50
 
63
51
  A working set is shipped at `src/@/globals.css` (for dev/test only).
64
52
 
65
- ### 3. Bundler alias
53
+ ### 2. Tailwind `@source` for this package
66
54
 
67
- ```ts
68
- // vite.config.ts
69
- resolve: { alias: { '@': fileURLToPath(new URL('./src/@', import.meta.url)) } }
55
+ Tailwind's scanner reads your CSS root plus its `@source` directives, and it
56
+ excludes `node_modules`. Classes that exist only inside this package's
57
+ components the whole navigation shell and footer therefore never reach your
58
+ stylesheet unless you point Tailwind at the built package:
59
+
60
+ ```css
61
+ @import "tailwindcss";
62
+
63
+ @source "../../../node_modules/@owlmeans/web-panel/src";
70
64
  ```
71
65
 
66
+ Adjust the relative depth to your own layout; the target is this package's
67
+ installed `src` directory.
68
+
69
+ ## Navigation shell
70
+
71
+ `NavLayout` is the standard application shell — header, section menu, the active
72
+ section's screen menu, content, footer. A layout entrypoint binds a component
73
+ that renders it and nothing else; the matched screen arrives as `children`.
74
+
75
+ ```tsx
76
+ import { NavLayout, HOME } from '@owlmeans/web-panel'
77
+ import type { PanelNavConfig, PanelNavLink } from '@owlmeans/web-panel'
78
+
79
+ const navConfig: PanelNavConfig = {
80
+ sections: [
81
+ { name: 'home', label: 'Home', items: [{ alias: HOME, label: 'Overview' }] },
82
+ {
83
+ name: 'demo', label: 'Demo', items: [
84
+ { alias: web.session, label: 'Session' },
85
+ { alias: web.about, label: 'About' },
86
+ ]
87
+ },
88
+ ],
89
+ }
90
+
91
+ const footerLinks: PanelNavLink[] = [
92
+ { alias: HOME, label: 'My App' },
93
+ { href: 'https://owlmeans.com', label: 'OwlMeans', open: true },
94
+ ]
95
+
96
+ export const MainLayout: FC<PropsWithChildren> = ({ children }) => (
97
+ <NavLayout nav={navConfig} title="My App" footer={footerLinks}>
98
+ {children}
99
+ </NavLayout>
100
+ )
101
+ ```
102
+
103
+ Navigation is **two-layer**: the top menu lists sections, the side menu lists the
104
+ active section's screens. A section holding a single screen renders **no side
105
+ menu at all**. `NavLayout` mounts `SideNav` twice — a `hidden md:block` column
106
+ beside the content and a `md:hidden` strip under the header — so the same items
107
+ serve wide and narrow viewports.
108
+
109
+ | Component | Props |
110
+ |---|---|
111
+ | `NavLayout` | `nav`, `translate?`, `title?`, `home?` (brand target; defaults to the first section's first item), `actions?`, `footer?` (`PanelNavLink[]` renders the standard footer, a node replaces it), `contentClassName?`, `className?`, `style?` |
112
+ | `TopNav` | `config`, `translate?`, `ariaLabel?`, `className?`, `style?` |
113
+ | `SideNav` | the same, plus `variant?: 'side' \| 'bar'` |
114
+ | `Footer` | `links?`, `translate?`, `children?`, `className?`, `style?` |
115
+
116
+ The navigation model itself (`usePanelNav`, `PanelNavConfig`, `PanelNavItem`,
117
+ `PanelNavSection`, `PanelNavLink`, `NavTranslate`) is headless and lives in
118
+ [`@owlmeans/client-panel`](../client-panel); these components are its shadcn
119
+ rendering.
120
+
121
+ Two things to know when wiring it:
122
+
123
+ - **Labels do not use i18n unless you pass a resolver.** `translate` is a prop
124
+ (`NavTranslate`), defaulting to one that returns the fallback, because an app
125
+ rendered without an i18n provider throws if a menu reads the panel i18n
126
+ context. Labels resolve as literal `label` → `translate(key, humanized)` →
127
+ humanized alias, with default keys `nav.<section>` and `modules.<alias>`.
128
+ - **A parent route needs a `default: true` child.** A frontend entrypoint with
129
+ children but no default child renders blank at its own path — give a grouping
130
+ screen an index child at `'/'`.
131
+
72
132
  ## Breaking changes vs `@owlmeans/mui-panel`
73
133
 
74
134
  This package keeps the same public name and re-export surface as the
@@ -103,14 +163,15 @@ Consumers that need the previous MUI behaviour should swap to
103
163
 
104
164
  ```ts
105
165
  import {
106
- PanelApp, Layout, Form, TextInput, SubmitButton, Button, ButtonSelector,
166
+ PanelApp, Layout, NavLayout, TopNav, SideNav, Footer,
167
+ Form, TextInput, SubmitButton, Button, ButtonSelector,
107
168
  Block, Text, Link, Status, ImageUploader,
108
169
  scalingToStyles, useBreakPoint, useMapBreakpoint,
109
170
  render,
110
171
  } from '@owlmeans/web-panel'
111
172
 
112
173
  import { setupExternalAuthentication } from '@owlmeans/web-panel/auth'
113
- import { modules } from '@owlmeans/web-panel/auth/modules'
174
+ import { entrypoints } from '@owlmeans/web-panel/auth/entrypoints'
114
175
  ```
115
176
 
116
177
  ## Related packages
@@ -130,7 +191,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
130
191
  your project's skill store (`.agents/skills/`):
131
192
 
132
193
  ```sh
133
- npx @owlmeans/agent-skills
194
+ npx @owlmeans/agent-skills@^0.1.18-rc.20
134
195
  ```
135
196
 
136
197
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/web-panel",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.516Z",
4
+ "version": "0.1.18-rc.40",
5
+ "generatedAt": "2026-09-12T14:18:54.798Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: web-panel
3
- description: How to use @owlmeans/web-panel — base browser context factory (makeContext) with shadcn/Radix + Tailwind and the default OwlMeans router wired in, plus form/panel components. Auto-invoked when building a web app's makeContext or importing web panel components.
3
+ description: How to use @owlmeans/web-panel — base browser context factory (makeContext) with shadcn/Radix + Tailwind and the default OwlMeans router wired in, plus the two-layer navigation shell (NavLayout/TopNav/SideNav/Footer) and form/panel components. Auto-invoked when building a web app's makeContext, wiring its navigation or layout, or importing web panel components.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,21 +8,41 @@ user-invocable: false
8
8
  # @owlmeans/web-panel
9
9
 
10
10
  **Layer:** Web (React)
11
- **Install:** `"@owlmeans/web-panel": "^0.1.18-rc.0"` in `dependencies`
11
+ **Install:** `"@owlmeans/web-panel": "^0.1.18-rc.40"` in `dependencies`
12
12
 
13
13
  ## Key Exports
14
14
 
15
15
  | Export | Description |
16
16
  |--------|-------------|
17
17
  | `makeContext<C, T>(cfg)` | Base web context factory (shadcn/Radix + default OwlMeans router) |
18
- | `components` submodule | shadcn/Radix panel/form components |
19
- | Re-exports from `@owlmeans/client-panel` | Cross-platform panel primitives |
20
- | `main`, `exports`, `context`, `modules`, `types` | Wiring helpers |
18
+ | `NavLayout` | The application shell — header, section menu, screen menu, content, footer |
19
+ | `TopNav` / `SideNav` / `Footer` | The shell's pieces, mountable on their own |
20
+ | `Toaster` | The application's toast surface mounted once, in the layout |
21
+ | `PanelMenu` | The dropdown menu, described as data — items, arbitrary widget rows, labels, separators and one level of submenu. `PanelMenuEntry` / `PanelMenuEntryKind` / `PanelMenuProps` come with it |
22
+ | `Link` | An `<a>` addressing an entrypoint alias (or a literal `src`), with the label taken from i18n |
23
+ | `LoginScreen` / `LocalizedLoginScreen` / `appendLoginScreen` | The identity-provider choice screen — see `login-methods` |
24
+ | `render(context, opts?)` | Mounts the tree inside `PanelApp`, with the browser language detector installed on the i18n instance. `opts` is `RenderOptions` plus `rootClassName` |
25
+ | `PanelApp` | That wrapper on its own — the themed root `div` plus the i18n provider — for a host that mounts the tree itself |
26
+ | `useContext<C, T>()` | The current context, from React. `AppContext` adds `context.flow()` over `@owlmeans/web-client`'s |
27
+ | `entrypoints` | The base declaration list — `@owlmeans/web-client`'s plus `@owlmeans/api-config-client`'s. Compose the app's own over it |
28
+ | `Block` / `Text` / `Status` | The shadcn `Card` panel with an optional `Actions` footer, a heading/paragraph whose copy comes from the panel namespace, and the shadcn `Alert` resolving a `ResilientError` to a translated message |
29
+ | `Form` / `TextInput` / `Button` / `SubmitButton` / `ButtonSelector` | The web form family. `Form` builds its own `useForm` + `ajvResolver` and borrows only `FormContext` and `schemaToFormDefault` from `@owlmeans/client-panel`; `TextInput` drives `react-hook-form`'s `Controller` directly, and the buttons call `handleSubmit` directly — none of them wraps `ClientForm`, `InputCtrl` or `ActionCtrl` |
30
+ | `ImageUploader` / `Layout` | The uploader in a drop target with a preview, and a plain content wrapper (the shell is `NavLayout`) |
31
+ | `scalingToStyles(h, v)` | `BlockScaling` → the width/height utility classes the panels share |
32
+ | `cn(...inputs)` | The class-name merger the components are written against — an app never re-declares it |
33
+ | `useIsMobile()` / `MOBILE_BREAKPOINT` | Viewport narrower than Tailwind's `md` (768), matched with `matchMedia` |
34
+ | `useBreakPoint()` | The current Tailwind breakpoint name, tracked on `resize` (`lg` when there is no `window`) |
35
+ | `useMapBreakpoint(map, def?, breakpoint?)` | The `map` entry for the current breakpoint (or for the `breakpoint` passed), falling back to `def`. It **throws a `SyntaxError`** when neither yields a value, so give it a `def` or cover every breakpoint |
36
+ | Re-exports from `@owlmeans/client-panel` | Cross-platform panel primitives, incl. `usePanelNav` and the `PanelNav*` types |
37
+ | Re-exports from `@owlmeans/client` / `@owlmeans/client-entrypoint` / `@owlmeans/route` | `bind`, `bindAll`, `bindScreen`, `handler`, `provideRequest`, `stab`, `route`, `croute`, `frontend`, `guard`, `useNavigate`, `useEntrypoint`, `useValue` |
38
+ | Re-exports from the surrounding layers | `config`, `service`, `addWebService`, `AppType` / `HOME` / `ROOT` / `BASE` / `GUEST`, `DISPATCHER`, `CAUTHEN_FLOW_ENTER`, `DAUTH_GUARD`, `setupExternalAuthentication`, `Dispatcher`, `appendWebAuthService`, `flow` / `configureFlows` / `useFlow` / `FLOW_PARAM` / `SERVICE_PARAM`, `useI18n*` / `useLanguage` / `composePrefix`, `addI18nApp` / `addI18nLib` / `SUPPORTED_LNGS` |
21
39
 
22
40
  ## Subpath Exports
23
41
 
24
42
  - `./auth` — auth panel components for web
25
- - `./auth/modules` — auth panel module declarations
43
+ - `./auth/entrypoints` — auth panel entrypoint declarations
44
+ - `./consent` — the cookie consent dialog and policy, bound to this app's i18n
45
+ - `./jobs` — `JobProgress`, `JobStatus`, `useJobToasts` over `@owlmeans/queue` records
26
46
 
27
47
  ## Usage
28
48
 
@@ -36,14 +56,335 @@ export const makeContext = <C extends Config, T extends Context<C>>(cfg: C): T =
36
56
  const context = makeBasicContext<C, T>(cfg)
37
57
  appendOidcGuard<C, T>(context)
38
58
  appendStateResource<C, T>(context, VIB_PROJECT_STATE)
39
- context.makeContext = makeContext as typeof context.makeContext
40
59
  return context
41
60
  }
42
61
  ```
43
62
 
63
+ **A context is created once per process, by one factory.** An app factory calls the factory of the
64
+ layer below it, applies idempotent `append*(context)` mixins, and returns that same context — the
65
+ whole shape of the file above. Nothing is stored for re-creation, and every service, resource and
66
+ entrypoint binds to exactly the one context it was appended to.
67
+
68
+ ### Navigation — `NavLayout`
69
+
70
+ `NavLayout` is the application shell. A layout entrypoint binds a component that renders it and
71
+ nothing else; the matched screen arrives as `children`. Keep the navigation as data in its own
72
+ module (`src/nav.ts`) so screens, entrypoints and the shell all read the same aliases.
73
+
74
+ ```tsx
75
+ import { NavLayout, HOME } from '@owlmeans/web-panel'
76
+ import type { PanelNavConfig, PanelNavLink } from '@owlmeans/web-panel'
77
+
78
+ export const navConfig: PanelNavConfig = {
79
+ sections: [
80
+ { name: 'home', label: 'Home', items: [{ alias: HOME, label: 'Overview' }] },
81
+ {
82
+ name: 'demo', label: 'Demo', items: [
83
+ { alias: web.session, label: 'Session' },
84
+ { alias: web.about, label: 'About' },
85
+ ]
86
+ },
87
+ ],
88
+ }
89
+
90
+ export const footerLinks: PanelNavLink[] = [
91
+ { alias: HOME, label: 'My App' },
92
+ { href: 'https://owlmeans.com', label: 'OwlMeans', open: true },
93
+ ]
94
+
95
+ export const MainLayout: FC<PropsWithChildren> = ({ children }) =>
96
+ <NavLayout nav={navConfig} title="My App" footer={footerLinks}>{children}</NavLayout>
97
+ ```
98
+
99
+ **Navigation is two-layer.** The top menu lists **sections** — the first level; the side menu lists
100
+ the **active section's screens** — the second. A section holding a single screen renders **no side
101
+ menu at all**: the model owns that rule (`showSide`), so a section that later grows a second screen
102
+ gains its menu with no layout change. `NavLayout` mounts `SideNav` twice — `variant="side"` as the
103
+ `hidden md:block` column beside the content, `variant="bar"` as the `md:hidden` strip under the
104
+ header. Both render the same items; only one is visible at a time.
105
+
106
+ | Component | Props |
107
+ |---|---|
108
+ | `NavLayout` | `nav: PanelNavConfig`, `translate?`, `title?: ReactNode`, `home?: string` (brand target — defaults to the first section's first item), `actions?: ReactNode`, `footer?: PanelNavLink[] \| ReactNode`, `headerClassName?`, `contentClassName?`, `containerClassName?`, `className?`, `style?` |
109
+ | `TopNav` | `config: PanelNavConfig`, `translate?`, `ariaLabel?`, `className?`, `style?` |
110
+ | `SideNav` | the same, plus `variant?: 'side' \| 'bar'` |
111
+ | `Footer` | `links?: PanelNavLink[]`, `translate?`, `containerClassName?` (the shell's rhythm, so the footer row lines up with the header and content), `children?`, `className?`, `style?` |
112
+
113
+ **The style slots are REGIONS, and each region is its own SURFACE.** `className` is the root —
114
+ the full-height page *behind* the header, side menu and footer. `headerClassName` is the sticky
115
+ top bar. `contentClassName` is the content area. `containerClassName` is width and padding for
116
+ all three at once, never colour.
117
+
118
+ The header paints an opaque background of its own, because it is sticky and content scrolls
119
+ beneath it. That makes it a **different surface from the root**, so it states `text-foreground`
120
+ alongside its `bg-background` — not as decoration, and not redundantly. A root carrying a
121
+ contrasting pair (`className="bg-primary text-primary-foreground"`, an ordinary dark shell)
122
+ otherwise inherits its near-white foreground into a near-white bar, and every header child that
123
+ states no colour of its own — the brand, a ghost-variant action button — is painted in the
124
+ foreground of a surface it is not on. It type-checks, it builds, it renders, and the menu is
125
+ invisible. Pinned by `tests/nav.spec.ts` → "the header is its own surface", which measures
126
+ rendered lightness rather than class names; the harness root carries a dark shell permanently so
127
+ every navigation test runs against that case.
128
+
129
+ **Every style slot is MERGED over its default — none of them substitutes.** `className`,
130
+ `headerClassName`, `contentClassName` and `containerClassName` all go through `cn`, so a caller
131
+ names only the utility it wants to move and tailwind-merge drops just the one it conflicts with.
132
+ This matters most for `containerClassName`, whose default is a four-part rhythm
133
+ (`mx-auto w-full max-w-6xl px-4`): a design asking for a wider page writes `max-w-[1280px]` and
134
+ means *wider*, not *unpadded and uncentred*. Substituting there took `px-4` and `mx-auto` down
135
+ with the width and left the header, content and footer all flush to the window edge. Pinned by
136
+ `nav.spec.ts` → "a width-only rhythm override keeps the side padding"; the harness passes a
137
+ width-only override permanently.
138
+
139
+ **A dark top bar is asked for with `headerClassName`**, giving it both halves
140
+ (`bg-secondary text-secondary-foreground`) — never by colouring the root and expecting the bar
141
+ to follow.
142
+
143
+ **The shell reads exactly these colour variables**: `--background` (page and top bar),
144
+ `--foreground` (active section link), `--muted-foreground` (resting section links),
145
+ `--accent`/`--accent-foreground` (active side-menu item), `--border` (the header, side-menu and
146
+ footer rules) and `--primary` — the footer renders its entries through `Link`, which paints
147
+ `text-primary`. It reads **no `--sidebar*` variable at all**. So `--muted-foreground` is not merely
148
+ the text colour of the `--muted` surface — it is secondary text sitting directly on `--background`,
149
+ and a theme that lightens it to suit a dark muted panel loses its top menu.
150
+
151
+ Rules that make the shell behave:
152
+
153
+ - **Labels never reach for i18n implicitly.** `translate` is a **prop** (`NavTranslate`), defaulting
154
+ to `defaultNavTranslate`, which returns the fallback. An app mounted with `renderApp` from
155
+ `@owlmeans/web-client` has no i18n provider, and the panel i18n hook dereferences `i18n.options`
156
+ on the empty object `react-i18next` returns without an instance — a throw inside render that
157
+ blanks the whole app. An app that does have i18n passes its own
158
+ `(key, defaultValue) => string` resolver. Order: literal `label` → `translate(key, humanized)` →
159
+ humanized alias. Default keys are
160
+ `nav.<section>` for sections and `modules.<alias>` for items and footer links — the same family
161
+ `Link` uses.
162
+ - **Menu entries are real links.** `TopNav` puts the resolved path on `href` and calls
163
+ `preventDefault()` in `onClick`, navigating in-app through `nav.press`. Never drop the `href`: an
164
+ `<a>` without one is not focusable, does not answer the keyboard, cannot be opened in a new tab,
165
+ and does not even carry the `link` role.
166
+ - **A parent route needs a `default: true` child.** A frontend entrypoint that has children but no
167
+ child declared `default: true` renders blank at its own path — give a grouping screen an index
168
+ child at `'/'`.
169
+ - **Vendor `navigation-menu`.** `SideNav` builds on the package-local `Button`; `TopNav` uses the
170
+ package-local shadcn `navigation-menu` primitive — see the package-boundary rule below.
171
+
172
+ ### Menus — `PanelMenu`
173
+
174
+ One dropdown, described as an ENTRY LIST rather than as children. Every kind has its own focus,
175
+ keyboard and close-on-select behaviour, so children would silently lose all three; and the same
176
+ description then serves a collapsed toolbar, a header overflow and a mobile shell without any of
177
+ them re-deriving it.
178
+
179
+ ```tsx
180
+ import { PanelMenu, PanelMenuEntryKind } from '@owlmeans/web-panel'
181
+ import type { PanelMenuEntry } from '@owlmeans/web-panel'
182
+
183
+ const entries: PanelMenuEntry[] = [
184
+ { kind: PanelMenuEntryKind.Widget, key: 'credits', render: <AccountCredits /> },
185
+ { kind: PanelMenuEntryKind.Separator, key: 'sep' },
186
+ { kind: PanelMenuEntryKind.Label, key: 'app', label: 'MyApp' },
187
+ { kind: PanelMenuEntryKind.Item, key: 'home', alias: HOME, Icon: House },
188
+ { kind: PanelMenuEntryKind.Item, key: 'docs', href: DOCS, open: true, hint: <ExternalLink className="size-3.5" /> },
189
+ { kind: PanelMenuEntryKind.Sub, key: 'lang', label: 'Language', hint: 'EN', entries: languages },
190
+ ]
191
+
192
+ <PanelMenu entries={entries} translate={t} triggerLabel="Menu" indicator={dot} align="end" />
193
+ ```
194
+
195
+ | Kind | What it is |
196
+ |---|---|
197
+ | `Item` | A focusable row that closes the menu. Exactly one of `alias` (an entrypoint) or `href`, the same union `PanelNavLink` uses; neither makes it a pure `onSelect` action. Also `Icon`, `hint` (right-aligned), `active`, `disabled`, `variant` |
198
+ | `Widget` | Arbitrary content as a plain ROW — see below |
199
+ | `Label` | A section heading |
200
+ | `Separator` | A rule between blocks |
201
+ | `Sub` | One nested level. A `Sub` inside a `Sub` renders nothing — a dropdown that nests further is a navigation tree, not this |
202
+
203
+ Rules the component owns, each of which was a real failure:
204
+
205
+ - **A `Widget` is a row, never a `DropdownMenuItem`.** An item takes both the focus and the
206
+ activation from the controls inside it: Radix's roving tabindex swallows the inner button's
207
+ keyboard access, and `onSelect` fires on any click that lands on the row — so a "Top up" button
208
+ inside an item dismisses the menu before its own handler is observed. The row takes no roving
209
+ focus and does not close the menu; the widget's own buttons are the click targets.
210
+ - **An in-app link cannot use `onSelect`.** The anchor must call `preventDefault()` or the browser
211
+ performs a full page load, and Radix composes its click handler with `checkForDefaultPrevented`
212
+ — so preventing the default also cancels `onSelect`, and with it the automatic close. `PanelMenu`
213
+ therefore navigates and closes explicitly from the anchor's own handler, and keeps its own open
214
+ state for that (a caller's `open`/`onOpenChange` still wins).
215
+ - **The href resolves synchronously.** `Link` asks `entrypoint.url()` and settles a frame later,
216
+ which is fine for a link already on screen; a menu's content mounts at the moment it opens, so an
217
+ href that arrives afterwards is missing exactly while the row is being read. `PanelMenu` uses
218
+ `entrypoint.path()` — a lookup — and answers `undefined` for a path carrying route parameters.
219
+ Never drop the `href`: an `<a>` without one is not focusable, does not answer the keyboard,
220
+ cannot be opened in a new tab, and does not carry the `link` role.
221
+ - **`hidden` takes the separators it orphans with it.** A caller composes the menu from optional
222
+ blocks; filtering the entries alone leaves a leading rule, a doubled rule, or one under the last
223
+ item. Normalisation is the whole reason the entries are data.
224
+ - **`translate` is a prop**, defaulting to `defaultNavTranslate` — same reason as the nav shell.
225
+ - `indicator` is a slot on the trigger's corner (a notification dot, a count), not a `tone` enum:
226
+ what deserves attention is the application's judgement.
227
+
228
+ ### Toasts — `Toaster`
229
+
230
+ An action that succeeded or failed says so in a toast. The surface is `Toaster`; the messages are
231
+ `toast.success(...)` / `toast.error(...)` imported from **`sonner`** by whatever raised them.
232
+
233
+ ```tsx
234
+ import { NavLayout, Toaster } from '@owlmeans/web-panel'
235
+
236
+ export const MainLayout: FC<PropsWithChildren> = ({ children }) => <>
237
+ <NavLayout nav={navConfig} title="My App">{children}</NavLayout>
238
+ <Toaster />
239
+ </>
240
+ ```
241
+
242
+ - **Mount it exactly once, in the layout.** `toast()` writes to a module-global store, so two
243
+ mounted `Toaster`s render every message twice and none renders any of them — both failures are
244
+ silent, which is why `tests/toaster.spec.ts` asserts the count rather than the presence.
245
+ - **Colours come from the app's own tokens** — `--popover`, `--popover-foreground`, `--border` —
246
+ so a toast matches every other floating surface. A caller's `style` merges over them.
247
+ - **The theme follows the `.dark` class on the document element**, not a theme provider: the
248
+ package reads the class an app's `next-themes`, the owl theme provider, or a hand-written
249
+ toggle all set, and depends on none of them. Pass `theme` explicitly to override.
250
+ - Defaults are `richColors`, `closeButton`, `duration={5000}`, `position="top-right"`; every one
251
+ of them, and every other `ToasterProps` field, is overridable per app.
252
+ - `sonner` is a dependency of this package, so nothing is required of the consumer — but an app
253
+ raising its own toasts should declare `sonner` too, at a range that resolves to the same copy.
254
+
255
+ ### Links — `Link`
256
+
257
+ `Link` renders an `<a>` whose `href` is the entrypoint's own answer: it asks
258
+ `entrypoint.url()` and puts the result on the anchor, so a link into another service comes out
259
+ absolute and a link inside this one comes out as a path. Address a screen by **alias** (or hand it
260
+ the entrypoint you already hold); `src` is the escape hatch for a literal URL.
261
+
262
+ ```tsx
263
+ import { Link } from '@owlmeans/web-panel'
264
+
265
+ <Link module={web.about} /> // label from `modules.<alias>`
266
+ <Link module={web.session} name="nav.session">Session</Link> // explicit i18n key
267
+ <Link src="https://owlmeans.com" open>OwlMeans</Link> // literal target, new tab
268
+ ```
269
+
270
+ Resolution is asynchronous — `href` is absent for the first paint and settles once the URL is
271
+ known — so never key a test or a layout on the anchor having an `href` synchronously. The label
272
+ falls back to `modules.<alias>` when neither `name` nor `children` is given, `open` adds
273
+ `target="_blank"` with `rel="noopener noreferrer"`, and `center` centres the text.
274
+
275
+ ### Forms — `Form`, `TextInput`, the buttons
276
+
277
+ `WebFormProps` is `@owlmeans/client-panel`'s `FormProps` plus `className` and `style`. `Form` holds
278
+ the whole model itself — `useForm` with `mode: 'all'`, `delayError: 300`, an `ajvResolver` over
279
+ `validation` with `coerceTypes` and the `ajv-formats` formats — and publishes it through
280
+ `FormProvider` plus `FormContext`, so every control below reads one form.
281
+
282
+ ```tsx
283
+ import { Form, TextInput, SubmitButton, Button } from '@owlmeans/web-panel'
284
+
285
+ <Form decorate validation={schema} onSubmit={async (data, update) => { await save(data); update(data) }}>
286
+ <TextInput name="email" label placeholder hint />
287
+ <TextInput name="password" type="password" label="Password" />
288
+ </Form>
289
+ ```
290
+
291
+ - **`decorate` switches the whole rendering.** With `decorate={true}` the fields go inside a shadcn
292
+ `Card`, the root error surfaces through `Status`, and a `SubmitButton` is rendered in the
293
+ `CardFooter` **whenever `onSubmit` is given** — the caller writes no action. Without it (the
294
+ default) `Form` is a bare flex column: no card, no root-error surface, no submit button, so the
295
+ caller renders its own action. `horizontal`/`vertical` scaling, `className` and `style` land on
296
+ the `Card` when decorated and on that column otherwise.
297
+ - **`formRef`** — a `useFormRef()` ref filled with `{ form, update, loader, error }`, which is how a
298
+ caller drives the form, flips the loader, or plants a field/root error from outside.
299
+ - **`TextInput` takes `label`, `placeholder` and `hint` as `string | boolean`.** `true` resolves
300
+ `<name>.label` / `<name>.placeholder` / `<name>.hint` from the form namespace; a string is used
301
+ verbatim; anything else renders nothing. It also takes `name`, `def`, `type` (any HTML input type,
302
+ default `text`) and `disableAutocomplete`. A field error replaces the hint line.
303
+ - **`Button`** takes a required `label`, `onClick`, `loader` (a `Toggleable` — open disables the
304
+ button and shows the spinner), `size` (`small`/`medium`/`large`), `fullWidth`, and `variant`,
305
+ which maps the MUI vocabulary onto shadcn (`contained` → `default`, `outlined` → `outline`,
306
+ `text` → `ghost`) and forwards a shadcn variant name unchanged.
307
+ - **`SubmitButton`** is that button bound to `handleSubmit`, taking `onSubmit` (or `onClick`) and a
308
+ `label` defaulting to `submit`. It resolves the label with the form `t` itself and passes it down
309
+ with `i18n.suppress` set, so the label is translated once.
310
+ - **`ButtonSelector`** renders one `Button` per entry of `options`, the one equal to `current`
311
+ `contained` and the rest `outlined`, calling `onSelect(option)`. `name` prefixes each option's
312
+ label key as `<name>.<option>`.
313
+
314
+ ## Subpath: `./jobs`
315
+
316
+ Three presentational pieces for a queue job, over `JobRecord` from `@owlmeans/queue`. They take
317
+ records — `@owlmeans/client-job`'s `useJobs()` maps straight onto them — and hold no store, no
318
+ socket and no strings of their own.
319
+
320
+ ```tsx
321
+ import { JobProgress, JobStatus, useJobToasts } from '@owlmeans/web-panel/jobs'
322
+
323
+ const jobs = useJobs().map(model => model.record)
324
+ useJobToasts(jobs)
325
+
326
+ <JobStatus job={job} labels={{ [JobState.Active]: t('jobs.running') }} />
327
+ <JobProgress job={job} />
328
+ ```
329
+
330
+ | Export | Description |
331
+ |---|---|
332
+ | `JobProgress` | The shadcn `Progress` bar. `job.progress` is read as a number, `{ percent }` or `{ done, total }`; anything else animates INDETERMINATE, because zero and "the processor never called `progress()`" look identical otherwise |
333
+ | `JobStatus` | The state pill. `data-state` carries the raw state, so a test never keys on the wording |
334
+ | `jobProgressValue(job)` | The percentage the bar shows, or `undefined` |
335
+ | `useJobToasts(jobs, opts?)` | One toast per job the first time it settles, on the `Toaster` the layout already mounts |
336
+
337
+ - **No packaged wording.** The states are broker vocabulary; the sentence an app wants for them
338
+ ("Queued", "Rendering", "Ready") is its own copy in its own namespace, so `JobStatus` takes a
339
+ `labels` map and otherwise renders the raw state — data, not an untranslated string.
340
+ - **`useJobToasts` never toasts on its first pass.** A screen opening onto a store seeded with
341
+ yesterday's finished jobs would fire a stack of them at once, so everything already settled at
342
+ mount is recorded as announced and only what settles afterwards is reported.
343
+ - It needs the same single `Toaster` as everything else — see above.
344
+
345
+ ## Subpath: `./consent`
346
+
347
+ `PanelCookieConsent` and `PanelCookiePolicy` — `@owlmeans/web-consent`'s components bound to this
348
+ app's language and translations, falling through to the package's own seven-language bundle for
349
+ every key the app has not overridden. See the `consent` skill.
350
+
351
+ A re-export does not move Tailwind class strings, so a consumer adds a second `@source` for
352
+ `@owlmeans/web-consent` alongside this package's — pointing at **`src`**, for the reason spelled out
353
+ under *Consumer setup* below. Without it the dialog renders half-styled.
354
+
355
+ ## Consumer setup — package boundary and Tailwind
356
+
357
+ `web-panel` ships its shadcn primitives and `cn` helper as private implementation files under its
358
+ own `build/@/` tree. Package source imports them only through relative specifiers; it must never
359
+ emit an absolute `@/…` import, because that alias belongs to the consuming application and makes a
360
+ fresh installation depend on unrelated files. Consumers import the public `cn` export when needed
361
+ and do not vendor this package's UI primitives.
362
+
363
+ Consumers still supply the package's peer dependencies: the Radix primitives (`label`,
364
+ `navigation-menu`, `progress`, `separator`, `slot`) plus React, Tailwind and the usual utility
365
+ libraries. A consumer may have its own shadcn `@` alias, but it is unrelated to this package.
366
+
367
+ Then point Tailwind at the installed package's **`src`** directory. Its oxide scanner reads the CSS root
368
+ plus `@source` directives only, and excludes `node_modules` — so classes that exist **only** inside
369
+ `web-panel` components (the whole navigation shell and footer) never reach the stylesheet, and the
370
+ app renders an unstyled menu. In the app's Tailwind entry:
371
+
372
+ ```css
373
+ @import "tailwindcss";
374
+
375
+ @source "../../../node_modules/@owlmeans/web-panel/src";
376
+ ```
377
+
378
+ Adjust the relative depth to your own layout. Source ships in the published tarball and is tracked
379
+ in a linked workspace, so it is the reliable scan target in both modes.
380
+
44
381
  ## Depends On
45
382
 
46
383
  - `@owlmeans/web-client`, `@owlmeans/client-panel`, `@owlmeans/client-i18n`, `@owlmeans/web-router`
384
+ - `@owlmeans/queue` — `JobRecord` / `JobState`, read by the `./jobs` subpath
47
385
  - Peers (app-provided): `react`, `react-dom`, `react-hook-form`, `tailwindcss`, `tailwind-merge`,
48
386
  `clsx`, `class-variance-authority`, `lucide-react`, `ajv`, and the `@radix-ui/react-*` primitives
49
- (`label`, `progress`, `separator`, `slot`). No MUI, no react-router.
387
+ (`label`, `navigation-menu`, `progress`, `separator`, `slot`). No MUI, no react-router.
388
+ - `ajv-formats` is imported at module scope by the form model but is declared in no dependency
389
+ section of the manifest, which lists `ajv` alone. An install that does not otherwise pull it in
390
+ fails at import time, so declare `ajv-formats` next to `ajv` in the consuming application.
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cva } from 'class-variance-authority';
3
- import { cn } from '@/lib/utils';
3
+ import { cn } from '../../lib/utils.js';
4
4
  const alertVariants = cva("relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", {
5
5
  variants: {
6
6
  variant: {
@@ -1 +1 @@
1
- {"version":3,"file":"alert.js","sourceRoot":"","sources":["../../../../src/@/components/ui/alert.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,MAAM,aAAa,GAAG,GAAG,CACvB,mOAAmO,EACnO;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,8BAA8B;YACvC,WAAW,EACT,mGAAmG;YACrG,OAAO,EACL,2FAA2F;SAC9F;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;KACnB;CACF,CACF,CAAA;AAED,SAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAO,EACP,GAAG,KAAK,EACyD;IACjE,OAAO,CACL,2BACY,OAAO,EACjB,IAAI,EAAC,OAAO,EACZ,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,KAChD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,6DAA6D,EAC7D,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACoB;IAC5B,OAAO,CACL,2BACY,mBAAmB,EAC7B,SAAS,EAAE,EAAE,CACX,gGAAgG,EAChG,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAA"}
1
+ {"version":3,"file":"alert.js","sourceRoot":"","sources":["../../../../src/@/components/ui/alert.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,MAAM,aAAa,GAAG,GAAG,CACvB,mOAAmO,EACnO;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,8BAA8B;YACvC,WAAW,EACT,mGAAmG;YACrG,OAAO,EACL,2FAA2F;SAC9F;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;KACnB;CACF,CACF,CAAA;AAED,SAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAO,EACP,GAAG,KAAK,EACyD;IACjE,OAAO,CACL,2BACY,OAAO,EACjB,IAAI,EAAC,OAAO,EACZ,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,KAChD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,6DAA6D,EAC7D,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACoB;IAC5B,OAAO,CACL,2BACY,mBAAmB,EAC7B,SAAS,EAAE,EAAE,CACX,gGAAgG,EAChG,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Slot } from '@radix-ui/react-slot';
3
3
  import { cva } from 'class-variance-authority';
4
- import { cn } from '@/lib/utils';
4
+ import { cn } from '../../lib/utils.js';
5
5
  const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive cursor-pointer", {
6
6
  variants: {
7
7
  variant: {
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/@/components/ui/button.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,MAAM,cAAc,GAAG,GAAG,CACxB,4cAA4c,EAC5c;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EACL,kEAAkE;YACpE,WAAW,EACT,6JAA6J;YAC/J,OAAO,EACL,uIAAuI;YACzI,SAAS,EACP,wEAAwE;YAC1E,KAAK,EACH,sEAAsE;YACxE,IAAI,EAAE,iDAAiD;SACxD;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,+BAA+B;YACxC,EAAE,EAAE,+CAA+C;YACnD,EAAE,EAAE,sCAAsC;YAC1C,IAAI,EAAE,QAAQ;SACf;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,SAAS;KAChB;CACF,CACF,CAAA;AAED,SAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAO,GAAG,KAAK,EACf,GAAG,KAAK,EAIP;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;IAEtC,OAAO,CACL,KAAC,IAAI,iBACO,QAAQ,EAClB,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,KACvD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/@/components/ui/button.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,MAAM,cAAc,GAAG,GAAG,CACxB,4cAA4c,EAC5c;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EACL,kEAAkE;YACpE,WAAW,EACT,6JAA6J;YAC/J,OAAO,EACL,uIAAuI;YACzI,SAAS,EACP,wEAAwE;YAC1E,KAAK,EACH,sEAAsE;YACxE,IAAI,EAAE,iDAAiD;SACxD;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,+BAA+B;YACxC,EAAE,EAAE,+CAA+C;YACnD,EAAE,EAAE,sCAAsC;YAC1C,IAAI,EAAE,QAAQ;SACf;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,SAAS;KAChB;CACF,CACF,CAAA;AAED,SAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAO,GAAG,KAAK,EACf,GAAG,KAAK,EAIP;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;IAEtC,OAAO,CACL,KAAC,IAAI,iBACO,QAAQ,EAClB,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,KACvD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { cn } from '@/lib/utils';
2
+ import { cn } from '../../lib/utils.js';
3
3
  function Card({ className, ...props }) {
4
4
  return (_jsx("div", { "data-slot": "card", className: cn("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className), ...props }));
5
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,SAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAChE,OAAO,CACL,2BACY,MAAM,EAChB,SAAS,EAAE,EAAE,CACX,mFAAmF,EACnF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,4JAA4J,EAC5J,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACrE,OAAO,CACL,2BACY,YAAY,EACtB,SAAS,EAAE,EAAE,CAAC,4BAA4B,EAAE,SAAS,CAAC,KAClD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAC3E,OAAO,CACL,2BACY,kBAAkB,EAC5B,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KACrD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,gEAAgE,EAChE,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACvE,OAAO,CACL,2BACY,cAAc,EACxB,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,KAC5B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,KAC/D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAChE,OAAO,CACL,2BACY,MAAM,EAChB,SAAS,EAAE,EAAE,CACX,mFAAmF,EACnF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,4JAA4J,EAC5J,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACrE,OAAO,CACL,2BACY,YAAY,EACtB,SAAS,EAAE,EAAE,CAAC,4BAA4B,EAAE,SAAS,CAAC,KAClD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAC3E,OAAO,CACL,2BACY,kBAAkB,EAC5B,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KACrD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,gEAAgE,EAChE,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACvE,OAAO,CACL,2BACY,cAAc,EACxB,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,KAC5B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,KAC/D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { cn } from '@/lib/utils';
2
+ import { cn } from '../../lib/utils.js';
3
3
  function Input({ className, type, ...props }) {
4
4
  return (_jsx("input", { type: type, "data-slot": "input", className: cn("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className), ...props }));
5
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../src/@/components/ui/input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,SAAS,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAiC;IACzE,OAAO,CACL,gBACE,IAAI,EAAE,IAAI,eACA,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,icAAic,EACjc,+EAA+E,EAC/E,wGAAwG,EACxG,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../src/@/components/ui/input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAiC;IACzE,OAAO,CACL,gBACE,IAAI,EAAE,IAAI,eACA,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,icAAic,EACjc,+EAA+E,EAC/E,wGAAwG,EACxG,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}