@jfrader/ui 0.7.1 → 0.7.3

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 (30) hide show
  1. package/README.md +13 -28
  2. package/dist/editable-details-BndqEnYF.js +365 -0
  3. package/dist/editable-details.js +2 -0
  4. package/dist/{flip-game-card-xmcR_QSq.js → flip-game-card-BOJIhBrh.js} +8 -4
  5. package/dist/flip-game-card.js +1 -1
  6. package/dist/index.js +92 -93
  7. package/dist/{locale-switcher-DTkySKsM.js → locale-switcher-Ce_tN4Gb.js} +2 -2
  8. package/dist/locale-switcher.js +1 -1
  9. package/dist/{billing-toggle-CgC7yxxo.js → toggle-subscription-Ytz7ew1q.js} +19 -19
  10. package/dist/toggle-subscription.js +2 -0
  11. package/dist/types/components/editable-details/editable-details.d.ts +58 -0
  12. package/dist/types/components/editable-details/index.d.ts +2 -0
  13. package/dist/types/components/locale-switcher/locale-switcher.d.ts +2 -2
  14. package/dist/types/components/toggle-subscription/index.d.ts +2 -0
  15. package/dist/types/components/toggle-subscription/toggle-subscription.d.ts +57 -0
  16. package/dist/types/index.d.ts +2 -3
  17. package/dist/types/styling/motion-timings.d.ts +8 -0
  18. package/dist/types/styling/theme.d.ts +2 -0
  19. package/package.json +10 -14
  20. package/dist/billing-toggle.js +0 -2
  21. package/dist/in-view-title-BUZCMqge.js +0 -225
  22. package/dist/in-view-title.js +0 -2
  23. package/dist/shortcut-recorder-VgTQdjjn.js +0 -688
  24. package/dist/shortcut-recorder.js +0 -2
  25. package/dist/types/components/billing-toggle/billing-toggle.d.ts +0 -57
  26. package/dist/types/components/billing-toggle/index.d.ts +0 -2
  27. package/dist/types/components/in-view-title/in-view-title.d.ts +0 -23
  28. package/dist/types/components/in-view-title/index.d.ts +0 -1
  29. package/dist/types/components/shortcut-recorder/index.d.ts +0 -2
  30. package/dist/types/components/shortcut-recorder/shortcut-recorder.d.ts +0 -117
package/README.md CHANGED
@@ -2,7 +2,15 @@
2
2
 
3
3
  React components styled with Emotion and themed through the CSS custom properties from `@jfrader/tokens`.
4
4
 
5
- ## Components
5
+ ## Start here
6
+
7
+ - [Getting started](https://github.com/jfrader/jfrader-ui/blob/master/docs/consuming-jfrader-ui.md): installation and complete React / Vite and Next.js examples.
8
+ - [Theming](https://github.com/jfrader/jfrader-ui/blob/master/docs/theming.md): light/dark palettes, brand accents and token overrides.
9
+ - [Styling](https://github.com/jfrader/jfrader-ui/blob/master/docs/styling.md): customize instances, public parts and reusable wrappers.
10
+
11
+ Requires React 19 and the `@jfrader/tokens/tokens.css` stylesheet. The same guides appear under **Foundations** in Storybook.
12
+
13
+ ## Component subpath examples
6
14
 
7
15
  | Subpath | Exports |
8
16
  | --- | --- |
@@ -22,6 +30,7 @@ React components styled with Emotion and themed through the CSS custom propertie
22
30
  | `@jfrader/ui/date-picker` | `DatePicker` |
23
31
  | `@jfrader/ui/dialog` | `Dialog` |
24
32
  | `@jfrader/ui/divider` | `Divider` |
33
+ | `@jfrader/ui/editable-details` | `EditableDetails` |
25
34
  | `@jfrader/ui/emblem` | `Emblem` |
26
35
  | `@jfrader/ui/flex` | `Flex` |
27
36
  | `@jfrader/ui/flip-game-card` | `FlipGameCard` |
@@ -47,7 +56,7 @@ React components styled with Emotion and themed through the CSS custom propertie
47
56
  | `@jfrader/ui/toggle-group` | `ToggleGroup` |
48
57
  | `@jfrader/ui/tooltip` | `Tooltip` |
49
58
 
50
- Each subpath also exports its prop types. The package root re-exports everything.
59
+ Each component subpath also exports its prop types. The package root re-exports component APIs; optional integrations such as `@jfrader/ui/next` and `@jfrader/ui/code-block/shiki` remain separate imports.
51
60
 
52
61
  ## Usage
53
62
 
@@ -67,35 +76,11 @@ import { ThemeRoot } from '@jfrader/ui/theme-root';
67
76
 
68
77
  ## Next.js App Router
69
78
 
70
- `@jfrader/ui/next` exports `EmotionRegistry`, the required Emotion registry. It needs the optional `next` and `@emotion/cache` peers:
71
-
72
- ```sh
73
- pnpm add @emotion/cache
74
- ```
75
-
76
- ```tsx
77
- // app/layout.tsx
78
- import { EmotionRegistry } from '@jfrader/ui/next';
79
-
80
- <body>
81
- <EmotionRegistry>{children}</EmotionRegistry>
82
- </body>;
83
- ```
84
-
85
- See [Next.js App Router](https://github.com/jfrader/jfrader-ui/blob/master/docs/consuming-jfrader-ui.md#nextjs-app-router) for Server Component boundaries.
79
+ Use the `EmotionRegistry` adapter from `@jfrader/ui/next`. See the complete [App Router layout](https://github.com/jfrader/jfrader-ui/blob/master/docs/consuming-jfrader-ui.md#nextjs-app-router), including dependencies and Server Component boundaries.
86
80
 
87
81
  ## Theming
88
82
 
89
- Components read CSS custom properties defined by `@jfrader/tokens`. Load the stylesheet once and wrap the app in `ThemeRoot`:
90
-
91
- ```tsx
92
- import '@jfrader/tokens/tokens.css';
93
- import { ThemeRoot } from '@jfrader/ui/theme-root';
94
-
95
- <ThemeRoot theme="light">{app}</ThemeRoot>;
96
- ```
97
-
98
- Token names and values live in `packages/tokens/src/tokens.ts`.
83
+ Set `data-theme` on `<html>` for the page, or use `ThemeRoot` for a subtree. `ThemeProvider` supplies styling callbacks with token references; it does not choose light or dark. See [Theming](https://github.com/jfrader/jfrader-ui/blob/master/docs/theming.md) for complete recipes and portal behavior.
99
84
 
100
85
  ## Build
101
86
 
@@ -0,0 +1,365 @@
1
+ 'use client';
2
+ import { i as e } from "./css-BYJhdGh-.js";
3
+ import { t } from "./disclosure-caret-C5T3fcl6.js";
4
+ import { n, t as r } from "./focus-ring-BK5W5_NY.js";
5
+ import { n as i, r as a } from "./media-8yrN85VT.js";
6
+ import { t as o } from "./sx-BJXJ2xJK.js";
7
+ import { t as s } from "./use-controlled-state-DpeVQZNR.js";
8
+ import { createContext as c, useCallback as l, useContext as u, useId as d, useLayoutEffect as f, useMemo as p, useRef as m } from "react";
9
+ import { vars as h } from "@jfrader/tokens/vars";
10
+ import { jsx as g, jsxs as _ } from "@emotion/react/jsx-runtime";
11
+ import { useMergeRefs as v } from "@floating-ui/react";
12
+ //#region src/components/editable-details/editable-details.tsx
13
+ var y = { edit: "Edit" }, b = {
14
+ 1: "h1",
15
+ 2: "h2",
16
+ 3: "h3",
17
+ 4: "h4",
18
+ 5: "h5",
19
+ 6: "h6"
20
+ }, x = c(y), S = c({
21
+ visible: !0,
22
+ triggers: []
23
+ }), C = e({
24
+ label: "editable-details",
25
+ display: "grid",
26
+ gap: h.space[6],
27
+ minInlineSize: 0,
28
+ maxInlineSize: "100%",
29
+ fontFamily: h.font.sans,
30
+ color: h.color.text,
31
+ lineHeight: h.lineHeight.base,
32
+ textAlign: "start",
33
+ overflowWrap: "anywhere"
34
+ }), w = e({ minInlineSize: 0 }), T = e({
35
+ margin: 0,
36
+ font: "inherit"
37
+ }), E = e({
38
+ display: "flex",
39
+ alignItems: "center",
40
+ justifyContent: "space-between",
41
+ gap: h.space[3],
42
+ inlineSize: "100%",
43
+ minInlineSize: 0,
44
+ minBlockSize: h.space[10],
45
+ paddingBlock: h.space[2],
46
+ paddingInlineStart: 0,
47
+ paddingInlineEnd: h.space[2],
48
+ border: 0,
49
+ background: "transparent",
50
+ color: "inherit",
51
+ font: "inherit",
52
+ fontWeight: h.fontWeight.semibold,
53
+ textAlign: "start",
54
+ overflowWrap: "anywhere",
55
+ cursor: "pointer",
56
+ "&::after": t,
57
+ "&[aria-expanded=\"true\"]::after": { transform: "rotate(90deg)" },
58
+ "&[aria-expanded=\"true\"]:dir(rtl)::after": { transform: "rotate(-90deg)" },
59
+ "&:hover": { backgroundColor: h.color.surfaceHover },
60
+ "&:focus-visible": r,
61
+ [a]: { "&::after": { transitionDuration: "0s" } },
62
+ [i]: { "&::after": {
63
+ forcedColorAdjust: "none",
64
+ borderInlineStartColor: "ButtonText"
65
+ } }
66
+ }), D = e({
67
+ display: "grid",
68
+ gap: h.space[4],
69
+ minInlineSize: 0,
70
+ paddingBlockStart: h.space[2],
71
+ "&[hidden]": { display: "none" }
72
+ }), O = e({
73
+ margin: 0,
74
+ minInlineSize: 0
75
+ }), k = e({
76
+ display: "flex",
77
+ flexWrap: "wrap",
78
+ gap: h.space[2],
79
+ minInlineSize: 0,
80
+ paddingBlock: h.space[3],
81
+ "&:where(:not(:last-child))": { borderBlockEnd: `1px solid ${h.color.border}` }
82
+ }), A = e({
83
+ flex: "1 1 10rem",
84
+ minInlineSize: 0,
85
+ color: h.color.textMuted,
86
+ fontWeight: h.fontWeight.regular
87
+ }), j = e({
88
+ flex: "2 1 16rem",
89
+ minInlineSize: 0,
90
+ margin: 0
91
+ }), M = e({
92
+ display: "flex",
93
+ flexWrap: "wrap",
94
+ alignItems: "start",
95
+ gap: h.space[2],
96
+ minInlineSize: 0
97
+ }), N = e({
98
+ flex: "1 1 8rem",
99
+ minInlineSize: 0
100
+ }), P = e({
101
+ minBlockSize: h.space[8],
102
+ paddingInline: h.space[2],
103
+ paddingBlock: h.space[1],
104
+ border: `1px solid ${h.color.borderControl}`,
105
+ borderRadius: h.radius.sm,
106
+ background: "transparent",
107
+ color: h.color.text,
108
+ font: "inherit",
109
+ cursor: "pointer",
110
+ "&:hover": { backgroundColor: h.color.surfaceHover },
111
+ "&:focus-visible": n,
112
+ [i]: {
113
+ borderColor: "ButtonText",
114
+ color: "ButtonText"
115
+ }
116
+ }), F = e({
117
+ minInlineSize: 0,
118
+ maxInlineSize: "100%",
119
+ "&:focus": r
120
+ });
121
+ function I(e) {
122
+ return e !== null && e.isConnected && e.getClientRects().length > 0 && !e.closest("[hidden], [inert]") && e.ownerDocument.defaultView?.getComputedStyle(e).visibility !== "hidden";
123
+ }
124
+ function L(e) {
125
+ for (let t of e) if (I(t.current)) {
126
+ t.current.focus();
127
+ return;
128
+ }
129
+ }
130
+ function R(e, t = !1) {
131
+ let n = m(null), r = m(!1);
132
+ return f(() => {
133
+ let i = e.current;
134
+ if (!i) return;
135
+ let a = i.ownerDocument;
136
+ n.current = a.activeElement;
137
+ let o = () => {
138
+ n.current = a.activeElement, (t || !i.contains(a.activeElement)) && (r.current = !1);
139
+ }, s = (e) => {
140
+ !e.defaultPrevented && (t || !e.composedPath().includes(i)) && (r.current = !1), !e.defaultPrevented && !e.composedPath().includes(i) && (n.current = null);
141
+ };
142
+ return a.addEventListener("focusin", o), a.addEventListener("mousedown", s), () => {
143
+ a.removeEventListener("focusin", o), a.removeEventListener("mousedown", s);
144
+ };
145
+ }, [e, t]), {
146
+ last: n,
147
+ intent: r
148
+ };
149
+ }
150
+ function z(e, t) {
151
+ let n = e.ownerDocument.activeElement;
152
+ return e.contains(n) || n === e.ownerDocument.body && t !== null && e.contains(t);
153
+ }
154
+ function B({ messages: e, className: t, sx: n, ...r }) {
155
+ let i = u(x), a = p(() => ({
156
+ ...i,
157
+ ...e
158
+ }), [i, e]);
159
+ return /* @__PURE__ */ g(x.Provider, {
160
+ value: a,
161
+ children: /* @__PURE__ */ g(o, {
162
+ className: t,
163
+ styles: C,
164
+ sx: n,
165
+ children: (e) => /* @__PURE__ */ g("div", {
166
+ ...r,
167
+ className: e,
168
+ "data-ui": "editable-details"
169
+ })
170
+ })
171
+ });
172
+ }
173
+ B.displayName = "EditableDetails";
174
+ function V({ ref: e, title: t, headingLevel: n = 3, open: r, defaultOpen: i = !1, onOpenChange: a, triggerRef: c, slotProps: l, children: h, className: y, sx: x, ...C }) {
175
+ let [O, k] = s(r, i, a), A = u(S), j = m(null), M = v([j, c]), N = m(null), P = R(N), F = d(), I = b[n], B = A.visible && !!O, V = p(() => [j, ...A.triggers], [A.triggers]), H = p(() => ({
176
+ visible: B,
177
+ triggers: V
178
+ }), [B, V]);
179
+ return f(() => {
180
+ let e = N.current;
181
+ !B && e && z(e, P.last.current) && L(H.triggers);
182
+ }, [
183
+ B,
184
+ H,
185
+ P.last
186
+ ]), /* @__PURE__ */ g(o, {
187
+ className: y,
188
+ styles: w,
189
+ sx: x,
190
+ children: (n) => /* @__PURE__ */ _("section", {
191
+ ...C,
192
+ ref: e,
193
+ className: n,
194
+ "data-ui": "editable-details-section",
195
+ "data-state": O ? "open" : "closed",
196
+ children: [/* @__PURE__ */ g(I, {
197
+ css: [T, l?.heading?.css],
198
+ className: l?.heading?.className,
199
+ children: /* @__PURE__ */ g("button", {
200
+ ref: M,
201
+ type: "button",
202
+ id: `${F}-trigger`,
203
+ "aria-expanded": !!O,
204
+ "aria-controls": `${F}-panel`,
205
+ onClick: () => k(!O),
206
+ css: [E, l?.trigger?.css],
207
+ className: l?.trigger?.className,
208
+ "data-ui": "editable-details-section-trigger",
209
+ children: t
210
+ })
211
+ }), /* @__PURE__ */ g(S.Provider, {
212
+ value: H,
213
+ children: /* @__PURE__ */ g("div", {
214
+ ref: N,
215
+ id: `${F}-panel`,
216
+ hidden: !O,
217
+ css: [D, l?.panel?.css],
218
+ className: l?.panel?.className,
219
+ "data-ui": "editable-details-section-panel",
220
+ children: h
221
+ })
222
+ })]
223
+ })
224
+ });
225
+ }
226
+ V.displayName = "EditableDetails.Section";
227
+ function H({ className: e, sx: t, ...n }) {
228
+ return /* @__PURE__ */ g(o, {
229
+ className: e,
230
+ styles: O,
231
+ sx: t,
232
+ children: (e) => /* @__PURE__ */ g("dl", {
233
+ ...n,
234
+ className: e,
235
+ "data-ui": "editable-details-list"
236
+ })
237
+ });
238
+ }
239
+ H.displayName = "EditableDetails.List";
240
+ function U({ renderEditor: e, labelId: t, hostId: n, part: r, edit: i, requestClose: a, focusIntent: o, acceptedClose: s }) {
241
+ let c = u(S), d = m(null), p = m(null), h = R(d), _ = m(!1), v = m(!1), y = h.intent, b = l((e) => (p.current = e, () => {
242
+ p.current === e && (p.current = null);
243
+ }), []), x = l(() => {
244
+ if (!_.current) return;
245
+ v.current = !0;
246
+ let e = d.current;
247
+ y.current = !!e && z(e, h.last.current), a();
248
+ }, [
249
+ a,
250
+ h.last,
251
+ y
252
+ ]);
253
+ return f(() => {
254
+ _.current = !0;
255
+ let e = d.current;
256
+ return () => {
257
+ if (_.current = !1, !e) return;
258
+ let t = z(e, h.last.current);
259
+ queueMicrotask(() => {
260
+ !e.isConnected && t && e.ownerDocument.activeElement === e.ownerDocument.body && (s.current && v.current && !y.current || (y.current && I(i.current) ? i.current.focus() : L(c.triggers)));
261
+ });
262
+ };
263
+ }, [
264
+ s,
265
+ i,
266
+ h.last,
267
+ y,
268
+ c.triggers
269
+ ]), f(() => {
270
+ if (!o.current) return;
271
+ o.current = !1;
272
+ let e = d.current;
273
+ e && c.visible && (I(p.current) && (p.current.focus(), e.ownerDocument.activeElement === p.current) || e.focus());
274
+ }, [o, c.visible]), /* @__PURE__ */ g("div", {
275
+ ref: d,
276
+ id: n,
277
+ role: "group",
278
+ "aria-labelledby": t,
279
+ tabIndex: -1,
280
+ className: r?.className,
281
+ css: [F, r?.css],
282
+ "data-ui": "editable-details-editor",
283
+ children: e({
284
+ initialFocusRef: b,
285
+ complete: x,
286
+ cancel: x,
287
+ visible: c.visible
288
+ })
289
+ });
290
+ }
291
+ function W({ ref: e, label: t, renderEditor: n, open: r, defaultOpen: i = !1, onOpenChange: a, children: c, slotProps: p, className: h, sx: y, ...b }) {
292
+ let [C, w, T] = s(r, n ? i : !1, a), E = u(S), D = u(x), O = m(null), F = m(null), I = R(O, !0), B = m(!!n), V = m(!1);
293
+ V.current = !C && !!n;
294
+ let H = d();
295
+ f(() => {
296
+ B.current && !n && (I.intent.current = !1, T()), B.current = !!n;
297
+ }, [
298
+ n,
299
+ T,
300
+ I.intent
301
+ ]);
302
+ let W = l((e) => (O.current = e, () => {
303
+ e && z(e, I.last.current) && queueMicrotask(() => {
304
+ !e.isConnected && e.ownerDocument.activeElement === e.ownerDocument.body && L(E.triggers);
305
+ }), O.current = null;
306
+ }), [I.last, E.triggers]), G = v([W, e]), K = l(() => w(!1), [w]), q = !!C && !!n;
307
+ return /* @__PURE__ */ g(o, {
308
+ className: h,
309
+ styles: k,
310
+ sx: y,
311
+ children: (e) => /* @__PURE__ */ _("div", {
312
+ ...b,
313
+ ref: G,
314
+ className: e,
315
+ "data-ui": "editable-details-item",
316
+ "data-state": q ? "open" : "closed",
317
+ children: [/* @__PURE__ */ g("dt", {
318
+ id: `${H}-label`,
319
+ css: [A, p?.label?.css],
320
+ className: p?.label?.className,
321
+ children: t
322
+ }), /* @__PURE__ */ g("dd", {
323
+ css: [j, p?.description?.css],
324
+ className: p?.description?.className,
325
+ children: q ? /* @__PURE__ */ g(U, {
326
+ renderEditor: n,
327
+ labelId: `${H}-label`,
328
+ hostId: `${H}-editor`,
329
+ part: p?.editor,
330
+ edit: F,
331
+ requestClose: K,
332
+ focusIntent: I.intent,
333
+ acceptedClose: V
334
+ }) : /* @__PURE__ */ _("div", {
335
+ css: [M, p?.summary?.css],
336
+ className: p?.summary?.className,
337
+ children: [/* @__PURE__ */ g("div", {
338
+ css: N,
339
+ children: c
340
+ }), n && /* @__PURE__ */ g("button", {
341
+ ref: F,
342
+ type: "button",
343
+ id: `${H}-edit`,
344
+ "aria-labelledby": `${H}-edit ${H}-label`,
345
+ onClick: () => {
346
+ I.intent.current = !0, w(!0);
347
+ },
348
+ css: [P, p?.edit?.css],
349
+ className: p?.edit?.className,
350
+ "data-ui": "editable-details-edit",
351
+ children: D.edit
352
+ })]
353
+ })
354
+ })]
355
+ })
356
+ });
357
+ }
358
+ W.displayName = "EditableDetails.Item";
359
+ var G = Object.assign(B, {
360
+ Section: V,
361
+ List: H,
362
+ Item: W
363
+ });
364
+ //#endregion
365
+ export { G as t };
@@ -0,0 +1,2 @@
1
+ 'use client';
2
+ export { t as EditableDetails } from "./editable-details-BndqEnYF.js";
@@ -22,7 +22,7 @@ var d = e({
22
22
  }, p = e({ "& > [data-ui=\"flip-game-card-rotator\"]": {
23
23
  transform: "none",
24
24
  transition: "none",
25
- "& > [data-ui=\"flip-game-card-back\"]": { transform: "none" }
25
+ "& > [aria-hidden=\"true\"]": { visibility: "hidden" }
26
26
  } }), m = e({
27
27
  "&[data-reduced-motion=\"true\"]": p,
28
28
  [t]: p
@@ -32,18 +32,21 @@ var d = e({
32
32
  blockSize: "100%",
33
33
  transformStyle: "preserve-3d",
34
34
  transform: "rotateY(0deg)",
35
- transition: `transform ${o.motion.duration.slow} ${o.motion.easeStandard}`,
35
+ transition: `transform ${o.motion.duration.cardFlip} ${o.motion.easeCardFlip}`,
36
36
  "&[data-state=\"back\"]": { transform: "rotateY(180deg)" }
37
37
  }), g = e({
38
38
  position: "absolute",
39
39
  inset: 0,
40
40
  backfaceVisibility: "hidden",
41
- "&[aria-hidden=\"true\"]": { visibility: "hidden" },
42
41
  "& > [data-ui=\"game-card\"]": {
43
42
  inlineSize: "100%",
44
43
  blockSize: "100%"
45
44
  }
46
- }), _ = e({ transform: "rotateY(180deg)" });
45
+ }), _ = e({
46
+ transform: "rotateY(180deg)",
47
+ "&[data-reduced-motion=\"true\"]": { transform: "none" },
48
+ [t]: { transform: "none" }
49
+ });
47
50
  function v({ ref: e, flipped: t, front: r, back: o, size: p = "md", slotProps: v, className: y, sx: b, ...x }) {
48
51
  let S = u(), [C, w] = a(!1);
49
52
  i(() => w(!0), []);
@@ -80,6 +83,7 @@ function v({ ref: e, flipped: t, front: r, back: o, size: p = "md", slotProps: v
80
83
  children: r
81
84
  }), /* @__PURE__ */ s("div", {
82
85
  "data-ui": "flip-game-card-back",
86
+ "data-reduced-motion": C && S || void 0,
83
87
  inert: !t,
84
88
  "aria-hidden": !t || void 0,
85
89
  className: v?.back?.className,
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- export { t as FlipGameCard } from "./flip-game-card-xmcR_QSq.js";
2
+ export { t as FlipGameCard } from "./flip-game-card-BOJIhBrh.js";