@fiestaboard/ui 5.6.0 → 5.7.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 (27) hide show
  1. package/dist/components/editor/color-picker-content.d.ts +25 -1
  2. package/dist/components/editor/color-picker-content.js +51 -44
  3. package/dist/components/editor/color-picker-content.js.map +1 -1
  4. package/dist/components/editor/draw-char-picker-content.d.ts +13 -3
  5. package/dist/components/editor/draw-char-picker-content.js +37 -36
  6. package/dist/components/editor/draw-char-picker-content.js.map +1 -1
  7. package/dist/components/editor/formatting-picker-content.js +10 -10
  8. package/dist/components/editor/template-editor-toolbar.d.ts +17 -1
  9. package/dist/components/editor/template-editor-toolbar.js +167 -163
  10. package/dist/components/editor/template-editor-toolbar.js.map +1 -1
  11. package/dist/components/editor/template-editor.d.ts +13 -1
  12. package/dist/components/editor/template-editor.js +132 -131
  13. package/dist/components/editor/template-editor.js.map +1 -1
  14. package/dist/components/feedback/badge.d.ts +23 -3
  15. package/dist/components/feedback/badge.js +29 -12
  16. package/dist/components/feedback/badge.js.map +1 -1
  17. package/dist/components/forms/button.d.ts +1 -1
  18. package/dist/components/forms/copy-button.d.ts +74 -0
  19. package/dist/components/forms/copy-button.js +49 -0
  20. package/dist/components/forms/copy-button.js.map +1 -0
  21. package/dist/components/forms/swatch.d.ts +40 -11
  22. package/dist/components/forms/swatch.js +40 -29
  23. package/dist/components/forms/swatch.js.map +1 -1
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.js +101 -100
  26. package/dist/theme.css +21 -8
  27. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
+ import { type Code62Glyph } from "../../lib/board-characters";
1
2
  import { type BoardColorName } from "../../lib/board-colors";
2
3
  import type { DeviceType } from "../../lib/board-dimensions";
3
4
  export interface ColorPickerLabels {
@@ -11,15 +12,38 @@ export interface ColorPickerLabels {
11
12
  colorNames: Record<BoardColorName, string>;
12
13
  /** Accessible name for one swatch, given its display name. */
13
14
  colorOptionLabel: (colorName: string) => string;
15
+ /**
16
+ * The code-62 button's wording, per glyph. Which of the two is used is
17
+ * decided by {@link resolveCode62Glyph}, not by the caller picking a
18
+ * string — a board that draws ♥ must never be offered a button captioned
19
+ * "degree", which is half of the bug FiestaBoard#1657 fixed.
20
+ */
14
21
  heartCharacterAriaLabel: string;
15
22
  heartLabel: string;
16
23
  insertHeartTooltip: string;
24
+ degreeCharacterAriaLabel: string;
25
+ degreeLabel: string;
26
+ insertDegreeTooltip: string;
17
27
  }
18
28
  export declare const DEFAULT_COLOR_PICKER_LABELS: ColorPickerLabels;
19
29
  export interface ColorPickerContentProps {
20
30
  /** Receives a template color token, e.g. `{{red}}` — or `°` for the Note heart. */
21
31
  onInsert: (colorValue: string) => void;
22
32
  deviceType?: DeviceType;
33
+ /**
34
+ * Which glyph the target board's character-code-62 flap draws.
35
+ *
36
+ * Resolved with {@link resolveCode62Glyph}: Note hardware only ever
37
+ * shipped the heart flap so this is ignored there, and an unset Flagship
38
+ * resolves to `"degree"` — the glyph every Flagship carried before the
39
+ * 2026 hardware change. A caller that has not been taught about the new
40
+ * flap therefore keeps rendering exactly as it did.
41
+ *
42
+ * This cannot be derived from `deviceType`. Since 2026 some Flagships ship
43
+ * a heart flap in that slot, so the glyph is a property of the individual
44
+ * board and only its owner knows (FiestaBoard#1657, #1664).
45
+ */
46
+ code62Glyph?: Code62Glyph;
23
47
  labels?: Partial<ColorPickerLabels>;
24
48
  }
25
- export declare function ColorPickerContent({ onInsert, deviceType, labels }: ColorPickerContentProps): import("react").JSX.Element;
49
+ export declare function ColorPickerContent({ onInsert, deviceType, code62Glyph, labels }: ColorPickerContentProps): import("react").JSX.Element;
@@ -5,11 +5,12 @@ import { Grid as n } from "../layout/grid.js";
5
5
  import { Text as r } from "../typography/text.js";
6
6
  import { Tooltip as i, TooltipContent as a, TooltipProvider as o, TooltipTrigger as s } from "../overlays/tooltip.js";
7
7
  import { AVAILABLE_COLORS as c, COLOR_DISPLAY as l } from "../../lib/board-colors.js";
8
- import { Heart as u } from "lucide-react";
9
- import { useRef as d, useState as f } from "react";
10
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
8
+ import { resolveCode62Glyph as u } from "../../lib/board-characters.js";
9
+ import { Heart as d, Thermometer as f } from "lucide-react";
10
+ import { useRef as p, useState as m } from "react";
11
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
11
12
  //#region src/components/editor/color-picker-content.tsx
12
- var h = {
13
+ var _ = {
13
14
  colorPickerAriaLabel: "Color picker",
14
15
  colorNames: {
15
16
  red: "Red",
@@ -24,95 +25,101 @@ var h = {
24
25
  colorOptionLabel: (e) => `${e} color`,
25
26
  heartCharacterAriaLabel: "Heart character",
26
27
  heartLabel: "heart",
27
- insertHeartTooltip: "Insert heart character (Note only)"
28
- }, g = c, _ = { red: "text-black" }, v = 4;
29
- function y({ onInsert: c, deviceType: y, labels: b }) {
30
- let x = {
31
- ...h,
32
- ...b
33
- }, S = y === "note", [C, w] = f(-1), T = d([]), E = (e) => {
34
- let t = (e % g.length + g.length) % g.length;
35
- w(t);
36
- let n = T.current[t];
28
+ insertHeartTooltip: "Insert heart character",
29
+ degreeCharacterAriaLabel: "Degree character",
30
+ degreeLabel: "degree",
31
+ insertDegreeTooltip: "Insert degree character"
32
+ }, v = c, y = { red: "text-black" }, b = 4;
33
+ function x({ onInsert: c, deviceType: x, code62Glyph: S, labels: C }) {
34
+ let w = {
35
+ ..._,
36
+ ...C
37
+ }, T = u(x ?? "flagship", S) === "heart", [E, D] = m(-1), O = p([]), k = (e) => {
38
+ let t = (e % v.length + v.length) % v.length;
39
+ D(t);
40
+ let n = O.current[t];
37
41
  n?.scrollIntoView({
38
42
  block: "nearest",
39
43
  behavior: "smooth"
40
44
  }), n?.focus();
41
45
  };
42
- return /* @__PURE__ */ p(o, { children: /* @__PURE__ */ m(t, {
43
- className: e("p-2", !S && "pb-1"),
46
+ return /* @__PURE__ */ h(o, { children: /* @__PURE__ */ g(t, {
47
+ className: e("p-2"),
44
48
  tabIndex: 0,
45
49
  role: "listbox",
46
- "aria-label": x.colorPickerAriaLabel,
50
+ "aria-label": w.colorPickerAriaLabel,
47
51
  onKeyDown: (e) => {
48
52
  switch (e.key) {
49
53
  case "ArrowRight":
50
- e.preventDefault(), E(C + 1);
54
+ e.preventDefault(), k(E + 1);
51
55
  break;
52
56
  case "ArrowLeft":
53
- e.preventDefault(), E(C - 1);
57
+ e.preventDefault(), k(E - 1);
54
58
  break;
55
59
  case "ArrowDown":
56
- e.preventDefault(), E(C + v);
60
+ e.preventDefault(), k(E + b);
57
61
  break;
58
62
  case "ArrowUp":
59
- e.preventDefault(), E(C - v);
63
+ e.preventDefault(), k(E - b);
60
64
  break;
61
65
  case "Enter":
62
- case " ": e.preventDefault(), c(`{{${g[C] ?? g[0]}}}`);
66
+ case " ": e.preventDefault(), c(`{{${v[E] ?? v[0]}}}`);
63
67
  }
64
68
  },
65
69
  onFocus: (e) => {
66
- e.target === e.currentTarget && C === -1 && E(0);
70
+ e.target === e.currentTarget && E === -1 && k(0);
67
71
  },
68
- children: [/* @__PURE__ */ p(n, {
72
+ children: [/* @__PURE__ */ h(n, {
69
73
  cols: "4",
70
74
  gap: "2",
71
75
  className: "w-64",
72
76
  role: "presentation",
73
- children: g.map((t, n) => {
74
- let o = C === n;
75
- return /* @__PURE__ */ m(i, { children: [/* @__PURE__ */ p(s, {
77
+ children: v.map((t, n) => {
78
+ let o = E === n;
79
+ return /* @__PURE__ */ g(i, { children: [/* @__PURE__ */ h(s, {
76
80
  asChild: !0,
77
- children: /* @__PURE__ */ p("button", {
81
+ children: /* @__PURE__ */ h("button", {
78
82
  ref: (e) => {
79
- T.current[n] = e;
83
+ O.current[n] = e;
80
84
  },
81
85
  type: "button",
82
86
  onClick: () => c(`{{${t}}}`),
83
- onFocus: () => w(n),
84
- className: e("h-10 rounded-md text-xs font-medium transition-all hover:scale-105 hover:shadow-md", "flex items-center justify-center focus:outline-none", o && "ring-2 ring-offset-2 ring-primary scale-105 shadow-md", l[t].bg, _[t] ?? l[t].text),
85
- "aria-label": x.colorOptionLabel(x.colorNames[t]),
87
+ onFocus: () => D(n),
88
+ className: e("h-10 rounded-md text-xs font-medium transition-all hover:scale-105 hover:shadow-md", "flex items-center justify-center focus:outline-none", o && "ring-2 ring-offset-2 ring-primary scale-105 shadow-md", l[t].bg, y[t] ?? l[t].text),
89
+ "aria-label": w.colorOptionLabel(w.colorNames[t]),
86
90
  role: "option",
87
91
  "aria-selected": o,
88
- children: x.colorNames[t]
92
+ children: w.colorNames[t]
89
93
  })
90
- }), /* @__PURE__ */ p(a, { children: /* @__PURE__ */ p(r, { children: x.colorNames[t] }) })] }, t);
94
+ }), /* @__PURE__ */ h(a, { children: /* @__PURE__ */ h(r, { children: w.colorNames[t] }) })] }, t);
91
95
  })
92
- }), S && /* @__PURE__ */ p(t, {
96
+ }), /* @__PURE__ */ h(t, {
93
97
  className: "mt-2 pt-2 border-t border-border",
94
98
  role: "presentation",
95
- children: /* @__PURE__ */ m(i, { children: [/* @__PURE__ */ p(s, {
99
+ children: /* @__PURE__ */ g(i, { children: [/* @__PURE__ */ h(s, {
96
100
  asChild: !0,
97
- children: /* @__PURE__ */ m("button", {
101
+ children: /* @__PURE__ */ g("button", {
98
102
  type: "button",
99
103
  onClick: () => c("°"),
100
- className: e("w-full h-10 rounded-md text-sm font-medium transition-all hover:scale-[1.02] hover:shadow-md", "flex items-center justify-center gap-1.5 focus:outline-none", "bg-board-red/10 text-board-red border border-board-red/20 hover:bg-board-red/20"),
101
- "aria-label": x.heartCharacterAriaLabel,
104
+ className: e("w-full h-10 rounded-md text-sm font-medium transition-all hover:scale-[1.02] hover:shadow-md", "flex items-center justify-center gap-1.5 focus:outline-none", T ? "bg-board-red/10 text-board-red border border-board-red/20 hover:bg-board-red/20" : "bg-muted text-foreground border border-input hover:bg-accent"),
105
+ "aria-label": T ? w.heartCharacterAriaLabel : w.degreeCharacterAriaLabel,
102
106
  role: "option",
103
107
  "aria-selected": !1,
104
- children: [/* @__PURE__ */ p(u, { className: "w-4 h-4 fill-current" }), /* @__PURE__ */ p(r, {
108
+ children: [T ? /* @__PURE__ */ h(d, { className: "w-4 h-4 fill-current" }) : /* @__PURE__ */ h(f, {
109
+ className: "w-4 h-4",
110
+ "aria-hidden": "true"
111
+ }), /* @__PURE__ */ h(r, {
105
112
  as: "span",
106
113
  weight: "medium",
107
- className: "text-board-red",
108
- children: x.heartLabel
114
+ className: T ? "text-board-red" : void 0,
115
+ children: T ? w.heartLabel : w.degreeLabel
109
116
  })]
110
117
  })
111
- }), /* @__PURE__ */ p(a, { children: /* @__PURE__ */ p(r, { children: x.insertHeartTooltip }) })] })
118
+ }), /* @__PURE__ */ h(a, { children: /* @__PURE__ */ h(r, { children: T ? w.insertHeartTooltip : w.insertDegreeTooltip }) })] })
112
119
  })]
113
120
  }) });
114
121
  }
115
122
  //#endregion
116
- export { y as ColorPickerContent, h as DEFAULT_COLOR_PICKER_LABELS };
123
+ export { x as ColorPickerContent, _ as DEFAULT_COLOR_PICKER_LABELS };
117
124
 
118
125
  //# sourceMappingURL=color-picker-content.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"color-picker-content.js","names":[],"sources":["../../../src/components/editor/color-picker-content.tsx"],"mappings":"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"}
1
+ {"version":3,"file":"color-picker-content.js","names":[],"sources":["../../../src/components/editor/color-picker-content.tsx"],"mappings":"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"}
@@ -1,11 +1,12 @@
1
+ import { type Code62Glyph } from "../../lib/board-characters";
1
2
  import type { DeviceType } from "../../lib/board-dimensions";
2
3
  import type { DrawBrush } from "./utils/draw-mode";
3
4
  export interface DrawCharPickerLabels {
4
5
  /** Accessible name for the character grid. */
5
6
  characters: string;
6
- /** Accessible name for the code-62 button on Flagship hardware. */
7
+ /** Accessible name for the code-62 button when the flap draws a degree sign. */
7
8
  degree: string;
8
- /** Accessible name for the code-62 button on a Note, where it draws a heart. */
9
+ /** Accessible name for the code-62 button when the flap draws a heart. */
9
10
  heart: string;
10
11
  }
11
12
  export declare const DEFAULT_DRAW_CHAR_PICKER_LABELS: DrawCharPickerLabels;
@@ -17,6 +18,15 @@ export interface DrawCharPickerContentProps {
17
18
  * the inserted character is the degree symbol either way.
18
19
  */
19
20
  deviceType?: DeviceType;
21
+ /**
22
+ * Which glyph the target board's code-62 flap draws. Same contract as
23
+ * {@link ColorPickerContent}: resolved with {@link resolveCode62Glyph},
24
+ * and unset means today's behaviour. Without it a 2026 heart-flap Flagship
25
+ * draws ° here while its board shows ♥, and announces "Degree" for a key
26
+ * that paints a heart — WCAG 1.1.1, and the same mismatch FiestaBoard#1657
27
+ * fixed in the colour picker.
28
+ */
29
+ code62Glyph?: Code62Glyph;
20
30
  labels?: Partial<DrawCharPickerLabels>;
21
31
  }
22
- export declare function DrawCharPickerContent({ current, onSelect, deviceType, labels }: DrawCharPickerContentProps): import("react").JSX.Element;
32
+ export declare function DrawCharPickerContent({ current, onSelect, deviceType, code62Glyph, labels, }: DrawCharPickerContentProps): import("react").JSX.Element;
@@ -2,71 +2,72 @@
2
2
  import { cn as e } from "../../lib/utils.js";
3
3
  import { Box as t } from "../layout/box.js";
4
4
  import { Grid as n } from "../layout/grid.js";
5
- import { DRAW_CHARS as r } from "./utils/draw-mode.js";
6
- import { useRef as i, useState as a } from "react";
7
- import { jsx as o } from "react/jsx-runtime";
5
+ import { resolveCode62Glyph as r } from "../../lib/board-characters.js";
6
+ import { DRAW_CHARS as i } from "./utils/draw-mode.js";
7
+ import { useRef as a, useState as o } from "react";
8
+ import { jsx as s } from "react/jsx-runtime";
8
9
  //#region src/components/editor/draw-char-picker-content.tsx
9
- var s = "°", c = "♥", l = {
10
+ var c = "°", l = "♥", u = {
10
11
  characters: "Characters",
11
12
  degree: "Degree",
12
13
  heart: "Heart"
13
- }, u = 8;
14
- function d({ current: d, onSelect: f, deviceType: p, labels: m }) {
15
- let h = {
16
- ...l,
17
- ...m
18
- }, g = p === "note", _ = d.kind === "char" ? d.char : null, v = i([]), [y, b] = a(() => {
19
- let e = _ ? r.indexOf(_) : -1;
14
+ }, d = 8;
15
+ function f({ current: f, onSelect: p, deviceType: m, code62Glyph: h, labels: g }) {
16
+ let _ = {
17
+ ...u,
18
+ ...g
19
+ }, v = r(m ?? "flagship", h) === "heart", y = f.kind === "char" ? f.char : null, b = a([]), [x, S] = o(() => {
20
+ let e = y ? i.indexOf(y) : -1;
20
21
  return e >= 0 ? e : 0;
21
- }), x = (e) => {
22
- let t = (e % r.length + r.length) % r.length;
23
- b(t), v.current[t]?.focus();
24
- }, S = (e, t) => {
22
+ }), C = (e) => {
23
+ let t = (e % i.length + i.length) % i.length;
24
+ S(t), b.current[t]?.focus();
25
+ }, w = (e, t) => {
25
26
  switch (e.key) {
26
27
  case "ArrowRight":
27
- e.preventDefault(), x(t + 1);
28
+ e.preventDefault(), C(t + 1);
28
29
  break;
29
30
  case "ArrowLeft":
30
- e.preventDefault(), x(t - 1);
31
+ e.preventDefault(), C(t - 1);
31
32
  break;
32
33
  case "ArrowDown":
33
- e.preventDefault(), x(t + u);
34
+ e.preventDefault(), C(t + d);
34
35
  break;
35
36
  case "ArrowUp":
36
- e.preventDefault(), x(t - u);
37
+ e.preventDefault(), C(t - d);
37
38
  break;
38
39
  case "Home":
39
- e.preventDefault(), x(0);
40
+ e.preventDefault(), C(0);
40
41
  break;
41
- case "End": e.preventDefault(), x(r.length - 1);
42
+ case "End": e.preventDefault(), C(i.length - 1);
42
43
  }
43
44
  };
44
- return /* @__PURE__ */ o(t, {
45
+ return /* @__PURE__ */ s(t, {
45
46
  className: "w-64 p-2",
46
47
  "data-testid": "draw-char-picker",
47
48
  role: "group",
48
- "aria-label": h.characters,
49
- children: /* @__PURE__ */ o(n, {
49
+ "aria-label": _.characters,
50
+ children: /* @__PURE__ */ s(n, {
50
51
  cols: "8",
51
52
  gap: "1",
52
- children: r.map((t, n) => {
53
- let r = t === s, i = r && g ? c : t;
54
- return /* @__PURE__ */ o("button", {
53
+ children: i.map((t, n) => {
54
+ let r = t === c, i = r && v ? l : t;
55
+ return /* @__PURE__ */ s("button", {
55
56
  ref: (e) => {
56
- v.current[n] = e;
57
+ b.current[n] = e;
57
58
  },
58
59
  type: "button",
59
60
  "data-draw-char": t,
60
- tabIndex: n === y ? 0 : -1,
61
- "aria-pressed": _ === t,
62
- "aria-label": r ? g ? h.heart : h.degree : t,
63
- onClick: () => f({
61
+ tabIndex: n === x ? 0 : -1,
62
+ "aria-pressed": y === t,
63
+ "aria-label": r ? v ? _.heart : _.degree : t,
64
+ onClick: () => p({
64
65
  kind: "char",
65
66
  char: t
66
67
  }),
67
- onFocus: () => b(n),
68
- onKeyDown: (e) => S(e, n),
69
- className: e("flex h-7 w-7 items-center justify-center rounded-md border font-mono text-sm transition-shadow", _ === t ? "ring-2 ring-primary ring-offset-1" : "hover:bg-muted/50"),
68
+ onFocus: () => S(n),
69
+ onKeyDown: (e) => w(e, n),
70
+ className: e("flex h-7 w-7 items-center justify-center rounded-md border font-mono text-sm transition-shadow", y === t ? "ring-2 ring-primary ring-offset-1" : "hover:bg-muted/50"),
70
71
  children: i
71
72
  }, t);
72
73
  })
@@ -74,6 +75,6 @@ function d({ current: d, onSelect: f, deviceType: p, labels: m }) {
74
75
  });
75
76
  }
76
77
  //#endregion
77
- export { l as DEFAULT_DRAW_CHAR_PICKER_LABELS, d as DrawCharPickerContent };
78
+ export { u as DEFAULT_DRAW_CHAR_PICKER_LABELS, f as DrawCharPickerContent };
78
79
 
79
80
  //# sourceMappingURL=draw-char-picker-content.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"draw-char-picker-content.js","names":[],"sources":["../../../src/components/editor/draw-char-picker-content.tsx"],"mappings":";;;;;;;;AA0BA,IAAM,IAAc,KAEd,IAAkB,KAWX,IAAwD;CACnE,YAAY;CACZ,QAAQ;CACR,OAAO;AACT,GAaM,IAAY;AAElB,SAAgB,EAAsB,EAAE,YAAS,aAAU,eAAY,aAAsC;CAC3G,IAAM,IAAI;EAAE,GAAG;EAAiC,GAAG;CAAO,GAIpD,IAAS,MAAe,QACxB,IAAe,EAAQ,SAAS,SAAS,EAAQ,OAAO,MACxD,IAAa,EAAqC,CAAC,CAAC,GAGpD,CAAC,GAAc,KAAmB,QAAe;EACrD,IAAM,IAAgB,IAAe,EAAW,QAAQ,CAAY,IAAI;EACxE,OAAO,KAAiB,IAAI,IAAgB;CAC9C,CAAC,GAEK,KAAa,MAAkB;EACnC,IAAM,KAAY,IAAQ,EAAW,SAAU,EAAW,UAAU,EAAW;EAE/E,AADA,EAAgB,CAAO,GACvB,EAAW,QAAQ,EAAQ,EAAE,MAAM;CACrC,GAEM,KAAiB,GAA+C,MAAkB;EACtF,QAAQ,EAAM,KAAd;GACE,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAC;IACnB;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAC;IACnB;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAS;IAC3B;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAS;IAC3B;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,CAAC;IACX;GACF,KAAK,OAEH,AADA,EAAM,eAAe,GACrB,EAAU,EAAW,SAAS,CAAC;EAEnC;CACF;CAEA,OAKE,kBAAC,GAAD;EAAK,WAAU;EAAW,eAAY;EAAmB,MAAK;EAAQ,cAAY,EAAE;EAClF,UAAA,kBAAC,GAAD;GAAM,MAAK;GAAI,KAAI;GAChB,UAAA,EAAW,KAAK,GAAM,MAAU;IAG/B,IAAM,IAAW,MAAS,GACpB,IAAQ,KAAY,IAAS,IAAkB;IAErD,OACE,kBAAC,UAAD;KAEE,MAAM,MAAO;MACX,EAAW,QAAQ,KAAS;KAC9B;KACA,MAAK;KACL,kBAAgB;KAChB,UAAU,MAAU,IAAe,IAAI;KACvC,gBAAc,MAAiB;KAC/B,cAAY,IAAY,IAAS,EAAE,QAAQ,EAAE,SAAU;KACvD,eAAe,EAAS;MAAE,MAAM;MAAQ;KAAK,CAAC;KAC9C,eAAe,EAAgB,CAAK;KACpC,YAAY,MAAU,EAAc,GAAO,CAAK;KAChD,WAAW,EACT,kGACA,MAAiB,IAAO,sCAAsC,mBAChE;KAEC,UAAA;IACK,GAlBD,CAkBC;GAEZ,CAAC;EACG,CAAA;CACH,CAAA;AAET"}
1
+ {"version":3,"file":"draw-char-picker-content.js","names":[],"sources":["../../../src/components/editor/draw-char-picker-content.tsx"],"mappings":";;;;;;;;;AA2BA,IAAM,IAAc,KAEd,IAAkB,KAWX,IAAwD;CACnE,YAAY;CACZ,QAAQ;CACR,OAAO;AACT,GAsBM,IAAY;AAElB,SAAgB,EAAsB,EACpC,YACA,aACA,eACA,gBACA,aAC6B;CAC7B,IAAM,IAAI;EAAE,GAAG;EAAiC,GAAG;CAAO,GAMpD,IAAU,EAAmB,KAAc,YAAY,CAAW,MAAM,SACxE,IAAe,EAAQ,SAAS,SAAS,EAAQ,OAAO,MACxD,IAAa,EAAqC,CAAC,CAAC,GAGpD,CAAC,GAAc,KAAmB,QAAe;EACrD,IAAM,IAAgB,IAAe,EAAW,QAAQ,CAAY,IAAI;EACxE,OAAO,KAAiB,IAAI,IAAgB;CAC9C,CAAC,GAEK,KAAa,MAAkB;EACnC,IAAM,KAAY,IAAQ,EAAW,SAAU,EAAW,UAAU,EAAW;EAE/E,AADA,EAAgB,CAAO,GACvB,EAAW,QAAQ,EAAQ,EAAE,MAAM;CACrC,GAEM,KAAiB,GAA+C,MAAkB;EACtF,QAAQ,EAAM,KAAd;GACE,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAC;IACnB;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAC;IACnB;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAS;IAC3B;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAS;IAC3B;GACF,KAAK;IAEH,AADA,EAAM,eAAe,GACrB,EAAU,CAAC;IACX;GACF,KAAK,OAEH,AADA,EAAM,eAAe,GACrB,EAAU,EAAW,SAAS,CAAC;EAEnC;CACF;CAEA,OAKE,kBAAC,GAAD;EAAK,WAAU;EAAW,eAAY;EAAmB,MAAK;EAAQ,cAAY,EAAE;EAClF,UAAA,kBAAC,GAAD;GAAM,MAAK;GAAI,KAAI;GAChB,UAAA,EAAW,KAAK,GAAM,MAAU;IAG/B,IAAM,IAAW,MAAS,GACpB,IAAQ,KAAY,IAAU,IAAkB;IAEtD,OACE,kBAAC,UAAD;KAEE,MAAM,MAAO;MACX,EAAW,QAAQ,KAAS;KAC9B;KACA,MAAK;KACL,kBAAgB;KAChB,UAAU,MAAU,IAAe,IAAI;KACvC,gBAAc,MAAiB;KAC/B,cAAY,IAAY,IAAU,EAAE,QAAQ,EAAE,SAAU;KACxD,eAAe,EAAS;MAAE,MAAM;MAAQ;KAAK,CAAC;KAC9C,eAAe,EAAgB,CAAK;KACpC,YAAY,MAAU,EAAc,GAAO,CAAK;KAChD,WAAW,EACT,kGACA,MAAiB,IAAO,sCAAsC,mBAChE;KAEC,UAAA;IACK,GAlBD,CAkBC;GAEZ,CAAC;EACG,CAAA;CACH,CAAA;AAET"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { cn as e } from "../../lib/utils.js";
3
- import { Badge as t } from "../feedback/badge.js";
4
- import { Button as n } from "../forms/button.js";
3
+ import { Button as t } from "../forms/button.js";
4
+ import { Badge as n } from "../feedback/badge.js";
5
5
  import { Input as r } from "../forms/input.js";
6
6
  import { Box as i } from "../layout/box.js";
7
7
  import { Flex as a } from "../layout/flex.js";
@@ -106,7 +106,7 @@ function S({ formatting: S = {}, onInsert: C, labels: w }) {
106
106
  maxLength: 10,
107
107
  "aria-labelledby": A,
108
108
  className: "flex-1 font-mono"
109
- }), /* @__PURE__ */ y(n, {
109
+ }), /* @__PURE__ */ y(t, {
110
110
  type: "submit",
111
111
  size: "sm",
112
112
  disabled: !O,
@@ -119,13 +119,13 @@ function S({ formatting: S = {}, onInsert: C, labels: w }) {
119
119
  className: "p-1.5 min-w-[240px] max-w-[280px]",
120
120
  children: /* @__PURE__ */ y(c, {
121
121
  gap: "0.5",
122
- children: j.map((n) => {
123
- let r = n.syntax.includes(h);
122
+ children: j.map((t) => {
123
+ let r = t.syntax.includes(h);
124
124
  return /* @__PURE__ */ b(l, { children: [/* @__PURE__ */ y(f, {
125
125
  asChild: !0,
126
126
  children: /* @__PURE__ */ b("button", {
127
127
  type: "button",
128
- onClick: () => M(n),
128
+ onClick: () => M(t),
129
129
  className: e("w-full text-left px-2.5 py-1.5 rounded-md text-sm", "hover:bg-accent hover:text-accent-foreground transition-colors", "flex items-center justify-between gap-2 group"),
130
130
  children: [/* @__PURE__ */ b(a, {
131
131
  align: "center",
@@ -135,15 +135,15 @@ function S({ formatting: S = {}, onInsert: C, labels: w }) {
135
135
  as: "span",
136
136
  weight: "medium",
137
137
  className: "capitalize truncate group-hover:text-accent-foreground",
138
- children: n.name
138
+ children: t.name
139
139
  })]
140
- }), r ? /* @__PURE__ */ y(g, { className: "w-3.5 h-3.5 text-muted-foreground group-hover:text-accent-foreground flex-shrink-0" }) : /* @__PURE__ */ y(t, {
140
+ }), r ? /* @__PURE__ */ y(g, { className: "w-3.5 h-3.5 text-muted-foreground group-hover:text-accent-foreground flex-shrink-0" }) : /* @__PURE__ */ y(n, {
141
141
  variant: "secondary",
142
142
  className: "font-mono text-[10px] px-1.5 py-0 flex-shrink-0",
143
- children: n.syntax
143
+ children: t.syntax
144
144
  })]
145
145
  })
146
- }), /* @__PURE__ */ y(u, { children: /* @__PURE__ */ y(s, { children: n.description ?? n.name }) })] }, n.syntax);
146
+ }), /* @__PURE__ */ y(u, { children: /* @__PURE__ */ y(s, { children: t.description ?? t.name }) })] }, t.syntax);
147
147
  })
148
148
  })
149
149
  }) });
@@ -1,8 +1,10 @@
1
1
  import type { Editor } from "@tiptap/react";
2
2
  import { type ComponentProps, type ReactNode } from "react";
3
+ import type { Code62Glyph } from "../../lib/board-characters";
3
4
  import { type BoardColorName } from "../../lib/board-colors";
4
5
  import { type ColorPickerLabels } from "./color-picker-content";
5
6
  import type { DeviceType } from "./constants";
7
+ import { type DrawCharPickerLabels } from "./draw-char-picker-content";
6
8
  import { type FormattingPickerLabels } from "./formatting-picker-content";
7
9
  import type { LineAlignment } from "./template-editor";
8
10
  import type { DrawBrush } from "./utils/draw-mode";
@@ -108,6 +110,13 @@ export interface TemplateEditorToolbarProps {
108
110
  onWrapToggle?: () => void;
109
111
  className?: string;
110
112
  deviceType?: DeviceType;
113
+ /**
114
+ * Which glyph the target board's code-62 flap draws. Forwarded to the
115
+ * colour picker and the draw-character picker; see
116
+ * {@link ColorPickerContent} for why it cannot be derived from
117
+ * `deviceType`.
118
+ */
119
+ code62Glyph?: Code62Glyph;
111
120
  onSyncFromBoard?: () => void;
112
121
  syncFromBoardPending?: boolean;
113
122
  drawMode?: boolean;
@@ -165,7 +174,14 @@ export interface TemplateEditorToolbarProps {
165
174
  variablePickerLabels?: Partial<VariablePickerLabels>;
166
175
  colorPickerLabels?: Partial<ColorPickerLabels>;
167
176
  formattingPickerLabels?: Partial<FormattingPickerLabels>;
177
+ /**
178
+ * Strings for the draw-character picker. Without this the toolbar rendered
179
+ * DrawCharPickerContent's three labels in English only, which is why
180
+ * FiestaBoard still renders that picker itself instead of adopting the
181
+ * toolbar's (#265).
182
+ */
183
+ drawCharPickerLabels?: Partial<DrawCharPickerLabels>;
168
184
  }
169
- declare function TemplateEditorToolbarImpl({ editor, currentAlignment, currentWrapEnabled, onAlignmentChange, onWrapToggle, className, deviceType, onSyncFromBoard, syncFromBoardPending, drawMode, onDrawModeToggle, drawBrush, onDrawBrushChange, templateVariables, isLoadingVariables, renderVariablePicker, pluginManifests, isLoadingManifests, pluginDisplayData, resolveIcon, entityPickerSlot, labels, variablePickerLabels, colorPickerLabels, formattingPickerLabels, }: TemplateEditorToolbarProps): import("react").JSX.Element;
185
+ declare function TemplateEditorToolbarImpl({ editor, currentAlignment, currentWrapEnabled, onAlignmentChange, onWrapToggle, className, deviceType, code62Glyph, onSyncFromBoard, syncFromBoardPending, drawMode, onDrawModeToggle, drawBrush, onDrawBrushChange, templateVariables, isLoadingVariables, renderVariablePicker, pluginManifests, isLoadingManifests, pluginDisplayData, resolveIcon, entityPickerSlot, labels, variablePickerLabels, colorPickerLabels, formattingPickerLabels, drawCharPickerLabels, }: TemplateEditorToolbarProps): import("react").JSX.Element;
170
186
  export declare const TemplateEditorToolbar: import("react").MemoExoticComponent<typeof TemplateEditorToolbarImpl>;
171
187
  export {};