@pihanga2/shadcn 0.2.1 → 0.2.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 (124) hide show
  1. package/AGENT.building-cards.md +208 -3
  2. package/AGENT.md +58 -3
  3. package/AGENT.using-cards.md +142 -4
  4. package/README.md +4 -12
  5. package/cards/badge/badge.component.js +1 -0
  6. package/cards/badge/badge.component.js.map +1 -1
  7. package/cards/box/box.component.js +2 -2
  8. package/cards/box/box.component.js.map +1 -1
  9. package/cards/box/box.types.d.ts +0 -8
  10. package/cards/box/box.types.js.map +1 -1
  11. package/cards/button/button.component.js +13 -13
  12. package/cards/button/button.types.d.ts +1 -0
  13. package/cards/button/button.types.js.map +1 -1
  14. package/cards/{chartGraph/chartGraph.component.d.ts → chart/chart.component.d.ts} +1 -1
  15. package/cards/chart/chart.types.d.ts +223 -0
  16. package/cards/chart/index.d.ts +1 -0
  17. package/cards/checkbox/checkbox.component.js +1 -0
  18. package/cards/checkbox/checkbox.component.js.map +1 -1
  19. package/cards/checkbox/checkbox.types.d.ts +4 -0
  20. package/cards/checkbox/checkbox.types.js +2 -2
  21. package/cards/checkbox/checkbox.types.js.map +1 -1
  22. package/cards/checkbox/index.js +5 -5
  23. package/cards/conditional/conditional.component.js +5 -5
  24. package/cards/conditional/conditional.types.d.ts +20 -5
  25. package/cards/conditional/conditional.types.js.map +1 -1
  26. package/cards/core-index.d.ts +3 -0
  27. package/cards/dataTable/dataTable.component.js +8 -8
  28. package/cards/dataTable/dataTable.types.js.map +1 -1
  29. package/cards/dataTable/dataTableRowDetail.component.js +1 -0
  30. package/cards/dataTable/dataTableRowDetail.component.js.map +1 -1
  31. package/cards/dialog/dialog.component.js +7 -7
  32. package/cards/dropDownMenu/drop-down.component.js +7 -7
  33. package/cards/field/field.component.js +4 -4
  34. package/cards/field/field.types.js.map +1 -1
  35. package/cards/fileDrop/fileDrop.component.js +90 -0
  36. package/cards/fileDrop/fileDrop.component.js.map +1 -0
  37. package/cards/fileDrop/fileDrop.types.js +11 -0
  38. package/cards/fileDrop/fileDrop.types.js.map +1 -0
  39. package/cards/fileDrop/index.js +13 -0
  40. package/cards/fileDrop/index.js.map +1 -0
  41. package/cards/flexGrid/flexGrid.component.js +1 -1
  42. package/cards/flexGrid/flexGrid.types.js.map +1 -1
  43. package/cards/form/form.component.js +6 -6
  44. package/cards/form/form.types.d.ts +4 -0
  45. package/cards/form/form.types.js +2 -2
  46. package/cards/form/form.types.js.map +1 -1
  47. package/cards/form/index.js +5 -5
  48. package/cards/framework/framework.component.js +4 -4
  49. package/cards/graphin/graphin.types.d.ts +37 -4
  50. package/cards/input/index.js +5 -5
  51. package/cards/input/input.component.js +1 -0
  52. package/cards/input/input.component.js.map +1 -1
  53. package/cards/input/input.types.d.ts +10 -2
  54. package/cards/input/input.types.js +2 -2
  55. package/cards/input/input.types.js.map +1 -1
  56. package/cards/list/list.component.js +32 -32
  57. package/cards/list/list.types.js +1 -0
  58. package/cards/list/list.types.js.map +1 -1
  59. package/cards/loadingOverlay/loadingOverlay.component.js +1 -1
  60. package/cards/loadingSkeleton/loading-skeleton.component.js +1 -1
  61. package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +5 -7
  62. package/cards/pageWithNavbar/pageWithNavbar.component.js +43 -43
  63. package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -1
  64. package/cards/pasteTarget/pasteTarget.component.js.map +1 -1
  65. package/cards/select/index.js +5 -5
  66. package/cards/select/select.component.js +1 -0
  67. package/cards/select/select.component.js.map +1 -1
  68. package/cards/select/select.types.d.ts +12 -0
  69. package/cards/select/select.types.js +2 -2
  70. package/cards/select/select.types.js.map +1 -1
  71. package/cards/slider/index.js +13 -0
  72. package/cards/slider/index.js.map +1 -0
  73. package/cards/slider/slider.component.js +64 -0
  74. package/cards/slider/slider.component.js.map +1 -0
  75. package/cards/slider/slider.types.d.ts +12 -4
  76. package/cards/slider/slider.types.js +7 -0
  77. package/cards/slider/slider.types.js.map +1 -0
  78. package/cards/sliderValue/index.js +12 -0
  79. package/cards/sliderValue/index.js.map +1 -0
  80. package/cards/sliderValue/sliderValue.component.js +33 -0
  81. package/cards/sliderValue/sliderValue.component.js.map +1 -0
  82. package/cards/sliderValue/sliderValue.types.js +7 -0
  83. package/cards/sliderValue/sliderValue.types.js.map +1 -0
  84. package/cards/stack/stack.component.js +5 -5
  85. package/cards/stack/stack.component.js.map +1 -1
  86. package/cards/stack/stack.types.js.map +1 -1
  87. package/cards/stepper/stepper.component.js +7 -7
  88. package/cards/switch/index.js +5 -5
  89. package/cards/switch/switch.component.js +1 -0
  90. package/cards/switch/switch.component.js.map +1 -1
  91. package/cards/switch/switch.types.d.ts +4 -0
  92. package/cards/switch/switch.types.js +2 -2
  93. package/cards/switch/switch.types.js.map +1 -1
  94. package/cards/tabs/tabs.component.js +6 -6
  95. package/cards/textField/index.js +5 -5
  96. package/cards/textField/textField.component.js +1 -0
  97. package/cards/textField/textField.component.js.map +1 -1
  98. package/cards/textField/textField.types.d.ts +4 -0
  99. package/cards/textField/textField.types.js +2 -2
  100. package/cards/textField/textField.types.js.map +1 -1
  101. package/cards/toast/index.js +7 -7
  102. package/cards/toast/toast.component.js +12 -12
  103. package/cards/toast/toast.component.js.map +1 -1
  104. package/cards/toast/toast.types.d.ts +4 -0
  105. package/cards/toast/toast.types.js +2 -2
  106. package/cards/toast/toast.types.js.map +1 -1
  107. package/cards/toggleGroup/index.js +5 -5
  108. package/cards/toggleGroup/toggleGroup.component.js +1 -0
  109. package/cards/toggleGroup/toggleGroup.component.js.map +1 -1
  110. package/cards/toggleGroup/toggleGroup.types.d.ts +4 -0
  111. package/cards/toggleGroup/toggleGroup.types.js +2 -2
  112. package/cards/toggleGroup/toggleGroup.types.js.map +1 -1
  113. package/cards/typography/typography.component.js +4 -4
  114. package/cards/typography/typography.types.js +1 -0
  115. package/cards/typography/typography.types.js.map +1 -1
  116. package/components/ui/slider.js +36 -0
  117. package/components/ui/slider.js.map +1 -0
  118. package/components/ui/toggle-group.js +1 -0
  119. package/components/ui/toggle-group.js.map +1 -1
  120. package/package.json +19 -8
  121. package/pihanga-shadcn.css +1 -1
  122. package/cards/chartGraph/chartGraph.types.d.ts +0 -102
  123. package/cards/chartGraph/index.d.ts +0 -1
  124. package/cards/core-index.js +0 -61
@@ -1,12 +1,12 @@
1
1
  import { Button as e } from "../../components/ui/button.js";
2
2
  import { Dialog as t, DialogBody as n, DialogContent as r, DialogDescription as i, DialogFooter as a, DialogHeader as o, DialogTitle as s, DialogTrigger as c } from "../../components/ui/dialog.js";
3
- import { Card as l } from "@pihanga2/core";
4
- import u from "react";
3
+ import l from "react";
4
+ import { Card as u } from "@pihanga2/core";
5
5
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
6
6
  //#region src/cards/dialog/dialog.component.tsx
7
7
  var p = (p) => {
8
- let { id: m, trigger: h, content: g, title: _, description: v, open: y, size: b, variant: x, desktopVariant: S, mobileVariant: C, dismissible: w, hideClose: T, className: E, footer: D, footerCloseButtonText: O, cardName: k, onOpened: A, onClosed: j, onOpenChanged: M } = p, N = O === void 0 ? "Close" : O, [P, F] = u.useState(!1), I = y ?? P, L = u.useRef(y);
9
- u.useEffect(() => {
8
+ let { id: m, trigger: h, content: g, title: _, description: v, open: y, size: b, variant: x, desktopVariant: S, mobileVariant: C, dismissible: w, hideClose: T, className: E, footer: D, footerCloseButtonText: O, cardName: k, onOpened: A, onClosed: j, onOpenChanged: M } = p, N = O === void 0 ? "Close" : O, [P, F] = l.useState(!1), I = y ?? P, L = l.useRef(y);
9
+ l.useEffect(() => {
10
10
  L.current === !0 && y === !1 && I === !1 && j({
11
11
  id: m,
12
12
  reason: "programmatic"
@@ -30,7 +30,7 @@ var p = (p) => {
30
30
  return h ? /* @__PURE__ */ d("span", {
31
31
  className: "inline-flex",
32
32
  "data-pihanga-trigger-wrapper": !0,
33
- children: /* @__PURE__ */ d(l, {
33
+ children: /* @__PURE__ */ d(u, {
34
34
  cardName: h,
35
35
  parentCard: k
36
36
  })
@@ -42,7 +42,7 @@ var p = (p) => {
42
42
  function V() {
43
43
  return D ? /* @__PURE__ */ d(a, {
44
44
  className: "bg-muted/50",
45
- children: /* @__PURE__ */ d(l, {
45
+ children: /* @__PURE__ */ d(u, {
46
46
  cardName: D,
47
47
  parentCard: k
48
48
  })
@@ -74,7 +74,7 @@ var p = (p) => {
74
74
  className: E,
75
75
  children: [
76
76
  B(),
77
- /* @__PURE__ */ d(n, { children: /* @__PURE__ */ d(l, {
77
+ /* @__PURE__ */ d(n, { children: /* @__PURE__ */ d(u, {
78
78
  cardName: g,
79
79
  parentCard: k
80
80
  }) }),
@@ -1,11 +1,11 @@
1
1
  import { DropdownOpenContext as e } from "./dropdown-context.js";
2
2
  import { DropdownMenu as t, DropdownMenuCheckboxItem as n, DropdownMenuContent as r, DropdownMenuGroup as i, DropdownMenuItem as a, DropdownMenuLabel as o, DropdownMenuRadioGroup as s, DropdownMenuRadioItem as c, DropdownMenuSeparator as l, DropdownMenuShortcut as u, DropdownMenuSub as d, DropdownMenuSubContent as f, DropdownMenuSubTrigger as p, DropdownMenuTrigger as m } from "./dropdown-menu.ui.js";
3
- import { Card as h } from "@pihanga2/core";
4
- import g from "react";
3
+ import h from "react";
4
+ import { Card as g } from "@pihanga2/core";
5
5
  import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
6
6
  //#region src/cards/dropDownMenu/drop-down.component.tsx
7
7
  var b = (b) => {
8
- let { trigger: x, menuLabel: S, menuAlign: C, items: w, cardName: T, checkboxCloseDelayMs: E } = b, [D, O] = g.useState(!1), k = g.useRef(null), [A, j] = g.useState({}), M = g.useCallback((e, t) => [...e, t].join("::"), []), N = g.useCallback((e, t = []) => {
8
+ let { trigger: x, menuLabel: S, menuAlign: C, items: w, cardName: T, checkboxCloseDelayMs: E } = b, [D, O] = h.useState(!1), k = h.useRef(null), [A, j] = h.useState({}), M = h.useCallback((e, t) => [...e, t].join("::"), []), N = h.useCallback((e, t = []) => {
9
9
  let n = {};
10
10
  if (!e?.length) return n;
11
11
  for (let r of e) if (!(!r || typeof r == "string")) {
@@ -36,9 +36,9 @@ var b = (b) => {
36
36
  k.current = null, O(!1);
37
37
  }, e);
38
38
  }
39
- g.useEffect(() => () => {
39
+ h.useEffect(() => () => {
40
40
  P();
41
- }, []), g.useEffect(() => {
41
+ }, []), h.useEffect(() => {
42
42
  D && j(N(w));
43
43
  }, [
44
44
  D,
@@ -51,7 +51,7 @@ var b = (b) => {
51
51
  "data-pihanga-trigger-wrapper": !0,
52
52
  children: /* @__PURE__ */ v(e.Provider, {
53
53
  value: D,
54
- children: /* @__PURE__ */ v(h, {
54
+ children: /* @__PURE__ */ v(g, {
55
55
  cardName: x,
56
56
  parentCard: T
57
57
  })
@@ -62,7 +62,7 @@ var b = (b) => {
62
62
  return S ? /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(o, { children: S }), /* @__PURE__ */ v(l, {})] }) : null;
63
63
  }
64
64
  function z(e) {
65
- return typeof e == "string" ? e : /* @__PURE__ */ v(h, {
65
+ return typeof e == "string" ? e : /* @__PURE__ */ v(g, {
66
66
  cardName: e,
67
67
  parentCard: T
68
68
  });
@@ -1,12 +1,12 @@
1
1
  import { cn as e } from "../../lib/utils.js";
2
2
  import { useFormContext as t } from "../form/form.context.js";
3
3
  import { Field as n, FieldDescription as r, FieldError as i, FieldLabel as a } from "../../components/ui/field.js";
4
- import { Card as o } from "@pihanga2/core";
5
- import s, { useMemo as c } from "react";
4
+ import o, { useMemo as s } from "react";
5
+ import { Card as c } from "@pihanga2/core";
6
6
  import { jsx as l, jsxs as u } from "react/jsx-runtime";
7
7
  //#region src/cards/field/field.component.tsx
8
8
  var d = (d) => {
9
- let { label: f, fieldCard: p, name: m, description: h, error: g, className: _, cardName: v } = d, y = t(), b = y.isInForm && m ? y.errors[m] : g, x = s.useId(), S = !!b, C = c(() => ({
9
+ let { label: f, fieldCard: p, name: m, description: h, error: g, className: _, cardName: v } = d, y = t(), b = y.isInForm && m ? y.errors[m] : g, x = o.useId(), S = !!b, C = s(() => ({
10
10
  cardName: p,
11
11
  parentCard: v,
12
12
  id: x,
@@ -26,7 +26,7 @@ var d = (d) => {
26
26
  htmlFor: x,
27
27
  children: f
28
28
  }),
29
- /* @__PURE__ */ l(o, { ...C }),
29
+ /* @__PURE__ */ l(c, { ...C }),
30
30
  h && /* @__PURE__ */ l(r, { children: h }),
31
31
  /* @__PURE__ */ l(i, { children: b })
32
32
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"field.types.js","names":[],"sources":["../../../src/cards/field/field.types.ts"],"sourcesContent":["import {createCardDeclaration, PiCardRef} from \"@pihanga2/core\";\n\nexport const PI_FIELD_CARD = \"pi/field\";\n\nexport const Field = createCardDeclaration<PiFieldProps>(PI_FIELD_CARD);\n\nexport type PiFieldProps = {\n /** Visible label rendered above the control. */\n label: string;\n\n /**\n * The Pihanga card reference for the plain control to render\n * (e.g. pi/text-field, pi/select, pi/checkbox, …).\n *\n * The field card will forward an `id` prop and an `invalid` boolean to the\n * inner card via Pihanga's standard prop-passing mechanism so the control\n * can wire up accessibility attributes without needing its own label logic.\n */\n fieldCard: PiCardRef;\n\n /**\n * Field name — when provided the card reads the current error from\n * FormContext (when inside a pi/form) to decide whether to show an error.\n */\n name?: string;\n\n /** Secondary help text rendered below the control. */\n description?: string;\n\n /**\n * Static error message. Overridden by the form-context error when `name`\n * is provided and the card is inside a pi/form.\n */\n error?: string;\n\n /** Additional CSS classes applied to the outer Field wrapper. */\n className?: string;\n};\n"],"mappings":";;AAEA,IAAa,IAAgB,YAEhB,IAAQ,EAAoC,CAAa"}
1
+ {"version":3,"file":"field.types.js","names":[],"sources":["../../../src/cards/field/field.types.ts"],"sourcesContent":["import {createCardDeclaration, type PiCardRef} from \"@pihanga2/core\";\n\nexport const PI_FIELD_CARD = \"pi/field\";\n\nexport const Field = createCardDeclaration<PiFieldProps>(PI_FIELD_CARD);\n\nexport type PiFieldProps = {\n /** Visible label rendered above the control. */\n label: string;\n\n /**\n * The Pihanga card reference for the plain control to render\n * (e.g. pi/text-field, pi/select, pi/checkbox, …).\n *\n * The field card will forward an `id` prop and an `invalid` boolean to the\n * inner card via Pihanga's standard prop-passing mechanism so the control\n * can wire up accessibility attributes without needing its own label logic.\n */\n fieldCard: PiCardRef;\n\n /**\n * Field name — when provided the card reads the current error from\n * FormContext (when inside a pi/form) to decide whether to show an error.\n */\n name?: string;\n\n /** Secondary help text rendered below the control. */\n description?: string;\n\n /**\n * Static error message. Overridden by the form-context error when `name`\n * is provided and the card is inside a pi/form.\n */\n error?: string;\n\n /** Additional CSS classes applied to the outer Field wrapper. */\n className?: string;\n};\n"],"mappings":";;AAEA,IAAa,IAAgB,YAEhB,IAAQ,EAAoC,CAAa"}
@@ -0,0 +1,90 @@
1
+ import { DEF_FILE_DROP_FILE_TYPES as e } from "./fileDrop.types.js";
2
+ /* empty css */
3
+ import "react";
4
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
5
+ import { FileUploader as r } from "react-drag-drop-files";
6
+ //#region src/cards/fileDrop/fileDrop.component.tsx
7
+ var i = Symbol.for("pihanga.card.FileDrop.LastDropped"), a = globalThis;
8
+ function o(e) {
9
+ let t = a[i] ??= null;
10
+ return t?.name === e ? t.file : null;
11
+ }
12
+ function s(e) {
13
+ a[i] = e;
14
+ }
15
+ function c() {
16
+ a[i] = null;
17
+ }
18
+ var l = (i) => {
19
+ let { fileTypes: a = e, title: o = "Click or drop a file right here", description: l, showProgress: u = !1, progress: d = 0, progressStyle: f = {}, dropStyle: p = {}, onFileDropped: m, onError: h, cardName: g, className: _, _cls: v } = i;
20
+ function y(e) {
21
+ let t = Array.isArray(e) ? e[0] : e;
22
+ if (!t) return;
23
+ let { name: n, size: r, type: i } = t;
24
+ s({
25
+ name: n,
26
+ file: t
27
+ }), m({
28
+ name: n,
29
+ size: r,
30
+ type: i
31
+ }), setTimeout(c, 2e3);
32
+ }
33
+ function b(e) {
34
+ h({ error: String(e) });
35
+ }
36
+ function x() {
37
+ let e = `${d}%`, r = `${e} Complete`, i = {
38
+ width: "50%",
39
+ ...f
40
+ };
41
+ return /* @__PURE__ */ n("div", {
42
+ className: "pi-progress",
43
+ children: [/* @__PURE__ */ t("div", {
44
+ className: "pi-progress-label",
45
+ children: e
46
+ }), /* @__PURE__ */ t("div", {
47
+ className: "pi-progress-container",
48
+ style: i,
49
+ children: /* @__PURE__ */ t("div", {
50
+ className: "pi-progress-bar",
51
+ style: { width: e },
52
+ role: "progressbar",
53
+ "aria-label": r
54
+ })
55
+ })]
56
+ });
57
+ }
58
+ function S() {
59
+ return /* @__PURE__ */ n("div", {
60
+ className: "dropzone-msg",
61
+ style: p,
62
+ children: [o && /* @__PURE__ */ t("h3", {
63
+ className: "dropzone-msg-title",
64
+ children: o
65
+ }), l && /* @__PURE__ */ t("span", {
66
+ className: "dropzone-msg-desc",
67
+ children: l
68
+ })]
69
+ });
70
+ }
71
+ function C() {
72
+ return /* @__PURE__ */ t(r, {
73
+ handleChange: y,
74
+ onTypeError: b,
75
+ name: "file",
76
+ types: a,
77
+ hoverTitle: " ",
78
+ children: S()
79
+ });
80
+ }
81
+ return /* @__PURE__ */ t("div", {
82
+ className: v("root", _),
83
+ "data-pihanga": g,
84
+ children: u ? x() : C()
85
+ });
86
+ };
87
+ //#endregion
88
+ export { l as FileDropComponent, o as get_last_dropped };
89
+
90
+ //# sourceMappingURL=fileDrop.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileDrop.component.js","names":[],"sources":["../../../src/cards/fileDrop/fileDrop.component.tsx"],"sourcesContent":["import React from \"react\";\nimport type {PiCardProps} from \"@pihanga2/core\";\nimport {FileUploader} from \"react-drag-drop-files\";\nimport {\n DEF_FILE_DROP_FILE_TYPES,\n type FileDropEvents,\n type FileDropProps,\n} from \"./fileDrop.types\";\nimport \"./fileDrop.css\";\n\ntype LastDropped = {name: string; file: File};\n\nconst KEY = Symbol.for(\"pihanga.card.FileDrop.LastDropped\");\n\nconst globalForCache = globalThis as unknown as Record<\n symbol,\n LastDropped | null | undefined\n>;\n\nexport function get_last_dropped(name: string): File | null {\n const slot = (globalForCache[KEY] ??= null);\n if (slot?.name === name) {\n return slot.file;\n }\n return null;\n}\n\nfunction setLastDropped(value: LastDropped): void {\n globalForCache[KEY] = value;\n}\n\nfunction clearLastDropped(): void {\n globalForCache[KEY] = null;\n}\n\nexport const FileDropComponent = (\n props: PiCardProps<FileDropProps, FileDropEvents>,\n): React.ReactNode => {\n const {\n fileTypes = DEF_FILE_DROP_FILE_TYPES,\n title = \"Click or drop a file right here\",\n description,\n showProgress = false,\n progress = 0,\n progressStyle = {},\n dropStyle = {},\n onFileDropped,\n onError,\n cardName,\n className,\n _cls,\n } = props;\n\n function handleChange(file: File | File[]): void {\n const f = Array.isArray(file) ? file[0] : file;\n if (!f) return;\n const {name, size, type} = f;\n setLastDropped({name, file: f});\n onFileDropped({name, size, type});\n // clean up reference to File in a few sec to avoid dangling reference\n setTimeout(clearLastDropped, 2000);\n }\n\n function handleTypeError(err: unknown): void {\n onError({error: String(err)});\n }\n\n function renderProgress(): React.ReactNode {\n const label = `${progress}%`;\n const msg = `${label} Complete`;\n const containerStyle = {width: \"50%\", ...progressStyle};\n return (\n <div className=\"pi-progress\">\n <div className=\"pi-progress-label\">{label}</div>\n <div\n className=\"pi-progress-container\"\n style={containerStyle as React.CSSProperties}\n >\n <div\n className=\"pi-progress-bar\"\n style={{width: label}}\n role=\"progressbar\"\n aria-label={msg}\n />\n </div>\n </div>\n );\n }\n\n function renderDropZone(): React.ReactElement {\n return (\n <div className=\"dropzone-msg\" style={dropStyle as React.CSSProperties}>\n {title && <h3 className=\"dropzone-msg-title\">{title}</h3>}\n {description && (\n <span className=\"dropzone-msg-desc\">{description}</span>\n )}\n </div>\n );\n }\n\n function renderFileUploader(): React.ReactNode {\n return (\n <FileUploader\n handleChange={handleChange}\n onTypeError={handleTypeError}\n name=\"file\"\n types={fileTypes}\n hoverTitle=\" \"\n >\n {renderDropZone()}\n </FileUploader>\n );\n }\n\n const cn = _cls(\"root\", className);\n return (\n <div className={cn} data-pihanga={cardName}>\n {showProgress ? renderProgress() : renderFileUploader()}\n </div>\n );\n};\n"],"mappings":";;;;;;AAYA,IAAM,IAAM,OAAO,IAAI,mCAAmC,GAEpD,IAAiB;AAKvB,SAAgB,EAAiB,GAA2B;CAC1D,IAAM,IAAQ,EAAe,OAAS;CAItC,OAHI,GAAM,SAAS,IACV,EAAK,OAEP;AACT;AAEA,SAAS,EAAe,GAA0B;CAChD,EAAe,KAAO;AACxB;AAEA,SAAS,IAAyB;CAChC,EAAe,KAAO;AACxB;AAEA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,eAAY,GACZ,WAAQ,mCACR,gBACA,kBAAe,IACf,cAAW,GACX,mBAAgB,CAAC,GACjB,eAAY,CAAC,GACb,kBACA,YACA,aACA,cACA,YACE;CAEJ,SAAS,EAAa,GAA2B;EAC/C,IAAM,IAAI,MAAM,QAAQ,CAAI,IAAI,EAAK,KAAK;EAC1C,IAAI,CAAC,GAAG;EACR,IAAM,EAAC,SAAM,SAAM,YAAQ;EAI3B,AAHA,EAAe;GAAC;GAAM,MAAM;EAAC,CAAC,GAC9B,EAAc;GAAC;GAAM;GAAM;EAAI,CAAC,GAEhC,WAAW,GAAkB,GAAI;CACnC;CAEA,SAAS,EAAgB,GAAoB;EAC3C,EAAQ,EAAC,OAAO,OAAO,CAAG,EAAC,CAAC;CAC9B;CAEA,SAAS,IAAkC;EACzC,IAAM,IAAQ,GAAG,EAAS,IACpB,IAAM,GAAG,EAAM,YACf,IAAiB;GAAC,OAAO;GAAO,GAAG;EAAa;EACtD,OACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAqB;GAAW,CAAA,GAC/C,kBAAC,OAAD;IACE,WAAU;IACV,OAAO;cAEP,kBAAC,OAAD;KACE,WAAU;KACV,OAAO,EAAC,OAAO,EAAK;KACpB,MAAK;KACL,cAAY;IACb,CAAA;GACE,CAAA,CACF;;CAET;CAEA,SAAS,IAAqC;EAC5C,OACE,kBAAC,OAAD;GAAK,WAAU;GAAe,OAAO;aAArC,CACG,KAAS,kBAAC,MAAD;IAAI,WAAU;cAAsB;GAAU,CAAA,GACvD,KACC,kBAAC,QAAD;IAAM,WAAU;cAAqB;GAAkB,CAAA,CAEtD;;CAET;CAEA,SAAS,IAAsC;EAC7C,OACE,kBAAC,GAAD;GACgB;GACd,aAAa;GACb,MAAK;GACL,OAAO;GACP,YAAW;aAEV,EAAe;EACJ,CAAA;CAElB;CAGA,OACE,kBAAC,OAAD;EAAK,WAFI,EAAK,QAAQ,CAEN;EAAI,gBAAc;YAC/B,IAAe,EAAe,IAAI,EAAmB;CACnD,CAAA;AAET"}
@@ -0,0 +1,11 @@
1
+ import { createCardDeclaration as e, createOnAction as t, registerActions as n } from "@pihanga2/core";
2
+ //#region src/cards/fileDrop/fileDrop.types.ts
3
+ var r = "shad/file-drop", i = e(r), a = n(r, ["file_dropped", "error"]), o = t(a.FILE_DROPPED), s = t(a.ERROR), c = [
4
+ "JPG",
5
+ "PNG",
6
+ "GIF"
7
+ ];
8
+ //#endregion
9
+ export { c as DEF_FILE_DROP_FILE_TYPES, a as FILE_DROP_ACTION, r as FILE_DROP_CARD, i as FileDrop, s as onFileDropError, o as onFileDropped };
10
+
11
+ //# sourceMappingURL=fileDrop.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileDrop.types.js","names":[],"sources":["../../../src/cards/fileDrop/fileDrop.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const FILE_DROP_CARD = \"shad/file-drop\";\n\nexport const FileDrop = createCardDeclaration<FileDropProps, FileDropEvents>(\n FILE_DROP_CARD,\n);\n\nexport const FILE_DROP_ACTION = registerActions(FILE_DROP_CARD, [\n \"file_dropped\",\n \"error\",\n]);\n\nexport const onFileDropped = createOnAction<FileDroppedEvent>(\n FILE_DROP_ACTION.FILE_DROPPED,\n);\n\nexport const onFileDropError = createOnAction<FileDropErrorEvent>(\n FILE_DROP_ACTION.ERROR,\n);\n\nexport type FileDropProps<S = Record<string, unknown>> = {\n /** Accepted file extensions, e.g. [\"JPG\", \"PNG\", \"PDF\"]. Defaults to [\"JPG\", \"PNG\", \"GIF\"]. */\n fileTypes?: string[];\n /** Heading shown inside the drop zone. */\n title?: string;\n /** Secondary text shown inside the drop zone. */\n description?: string;\n /** When true, shows a progress bar instead of the drop zone. */\n showProgress?: boolean;\n /** Inline styles applied to the drop zone wrapper. */\n dropStyle?: Record<string, unknown>;\n /** Inline styles applied to the progress bar container. */\n progressStyle?: Record<string, unknown>;\n /** Current upload progress (0–100). Only used when `showProgress` is true. */\n progress?: number;\n\n style?: S;\n className?: string;\n};\n\nexport const DEF_FILE_DROP_FILE_TYPES = [\"JPG\", \"PNG\", \"GIF\"];\n\nexport type FileDroppedEvent = {\n name: string;\n size: number;\n type: string;\n};\n\nexport type FileDropErrorEvent = {\n error: string;\n};\n\nexport type FileDropEvents = {\n onFileDropped: FileDroppedEvent;\n onError: FileDropErrorEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAiB,kBAEjB,IAAW,EACtB,CACF,GAEa,IAAmB,EAAgB,GAAgB,CAC9D,gBACA,OACF,CAAC,GAEY,IAAgB,EAC3B,EAAiB,YACnB,GAEa,IAAkB,EAC7B,EAAiB,KACnB,GAsBa,IAA2B;CAAC;CAAO;CAAO;AAAK"}
@@ -0,0 +1,13 @@
1
+ import { DEF_FILE_DROP_FILE_TYPES as e, FILE_DROP_ACTION as t, FILE_DROP_CARD as n, FileDrop as r, onFileDropError as i, onFileDropped as a } from "./fileDrop.types.js";
2
+ import { FileDropComponent as o, get_last_dropped as s } from "./fileDrop.component.js";
3
+ import { actionTypesToEvents as c, registerCardComponent as l } from "@pihanga2/core";
4
+ //#region src/cards/fileDrop/index.ts
5
+ l({
6
+ name: n,
7
+ component: o,
8
+ events: c(t)
9
+ });
10
+ //#endregion
11
+ export { e as DEF_FILE_DROP_FILE_TYPES, t as FILE_DROP_ACTION, n as FILE_DROP_CARD, r as FileDrop, s as get_last_dropped, i as onFileDropError, a as onFileDropped };
12
+
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/cards/fileDrop/index.ts"],"sourcesContent":["import {actionTypesToEvents, registerCardComponent} from \"@pihanga2/core\";\n\nimport {FileDropComponent} from \"./fileDrop.component\";\nimport {FILE_DROP_ACTION, FILE_DROP_CARD} from \"./fileDrop.types\";\n\nexport * from \"./fileDrop.types\";\nexport {get_last_dropped} from \"./fileDrop.component\";\n\nregisterCardComponent({\n name: FILE_DROP_CARD,\n component: FileDropComponent,\n events: actionTypesToEvents(FILE_DROP_ACTION),\n});\n"],"mappings":";;;;AAQA,EAAsB;CACpB,MAAM;CACN,WAAW;CACX,QAAQ,EAAoB,CAAgB;AAC9C,CAAC"}
@@ -1,5 +1,5 @@
1
- import { Card as e } from "@pihanga2/core";
2
1
  import "react";
2
+ import { Card as e } from "@pihanga2/core";
3
3
  import t from "clsx";
4
4
  import { jsx as n } from "react/jsx-runtime";
5
5
  //#region src/cards/flexGrid/flexGrid.component.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"flexGrid.types.js","names":[],"sources":["../../../src/cards/flexGrid/flexGrid.types.ts"],"sourcesContent":["import { createCardDeclaration, PiCardRef } from \"@pihanga2/core\"\n\nexport const FLEX_GRID_CARD = \"flex_grid\"\nexport const FlexGrid = createCardDeclaration<FlexGridProps>(FLEX_GRID_CARD)\n\nexport type FlexGridProps = {\n cards: { [name: string]: PiCardRef }\n template: TemplateT\n height?: string\n margin?: string\n overflow?: string\n\n style?: {\n root?: React.CSSProperties\n item?: React.CSSProperties\n }\n className?: string\n}\n\n// body {\n// display: grid;\n// grid-template-areas:\n// \"header header header\"\n// \"nav article ads\"\n// \"footer footer footer\";\n// grid-template-rows: 60px 1fr 60px;\n// grid-template-columns: 20% 1fr 15%;\n// grid-gap: 10px;\n// height: 100vh;\n// margin: 0;\n// }\n\n// https://css-tricks.com/snippets/css/complete-guide-grid/\nexport type TemplateT = {\n area?: string[][] // name of card dict\n rows?: string[] // grid-template-rows (e.g [\"min-content\", \"1fr\", \"min-content\"])\n columns?: string[] // grid-template-cols (e.g. [\"1fr\", \"50px\", \"1fr\", \"1fr\"])\n gap?: string\n}\n"],"mappings":";;AAEA,IAAa,IAAiB,aACjB,IAAW,EAAqC,CAAc"}
1
+ {"version":3,"file":"flexGrid.types.js","names":[],"sources":["../../../src/cards/flexGrid/flexGrid.types.ts"],"sourcesContent":["import {createCardDeclaration, type PiCardRef} from \"@pihanga2/core\";\n\nexport const FLEX_GRID_CARD = \"flex_grid\";\nexport const FlexGrid = createCardDeclaration<FlexGridProps>(FLEX_GRID_CARD);\n\nexport type FlexGridProps = {\n cards: {[name: string]: PiCardRef};\n template: TemplateT;\n height?: string;\n margin?: string;\n overflow?: string;\n\n style?: {\n root?: React.CSSProperties;\n item?: React.CSSProperties;\n };\n className?: string;\n};\n\n// body {\n// display: grid;\n// grid-template-areas:\n// \"header header header\"\n// \"nav article ads\"\n// \"footer footer footer\";\n// grid-template-rows: 60px 1fr 60px;\n// grid-template-columns: 20% 1fr 15%;\n// grid-gap: 10px;\n// height: 100vh;\n// margin: 0;\n// }\n\n// https://css-tricks.com/snippets/css/complete-guide-grid/\nexport type TemplateT = {\n area?: string[][]; // name of card dict\n rows?: string[]; // grid-template-rows (e.g [\"min-content\", \"1fr\", \"min-content\"])\n columns?: string[]; // grid-template-cols (e.g. [\"1fr\", \"50px\", \"1fr\", \"1fr\"])\n gap?: string;\n};\n"],"mappings":";;AAEA,IAAa,IAAiB,aACjB,IAAW,EAAqC,CAAc"}
@@ -1,11 +1,11 @@
1
1
  import { cn as e } from "../../lib/utils.js";
2
2
  import { FormContext as t } from "./form.context.js";
3
- import { Card as n } from "@pihanga2/core";
4
- import { useCallback as r, useState as i } from "react";
3
+ import { useCallback as n, useState as r } from "react";
4
+ import { Card as i } from "@pihanga2/core";
5
5
  import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
6
  //#region src/cards/form/form.component.tsx
7
7
  var s = (s) => {
8
- let { id: c, content: l = [], initialValues: u = {}, submitLabel: d = "Submit", className: f, cardName: p, onSubmitted: m } = s, [h, g] = i(() => ({ ...u })), [_, v] = i({}), y = r((e, t) => {
8
+ let { id: c, content: l = [], initialValues: u = {}, submitLabel: d = "Submit", className: f, cardName: p, onSubmitted: m } = s, [h, g] = r(() => ({ ...u })), [_, v] = r({}), y = n((e, t) => {
9
9
  g((n) => ({
10
10
  ...n,
11
11
  [e]: t
@@ -14,7 +14,7 @@ var s = (s) => {
14
14
  let n = { ...t };
15
15
  return delete n[e], n;
16
16
  });
17
- }, []), b = r((e, t) => {
17
+ }, []), b = n((e, t) => {
18
18
  v((n) => {
19
19
  if (t === null) {
20
20
  let t = { ...n };
@@ -25,7 +25,7 @@ var s = (s) => {
25
25
  [e]: t
26
26
  };
27
27
  });
28
- }, []), x = r((e) => {
28
+ }, []), x = n((e) => {
29
29
  e.preventDefault(), m({
30
30
  id: c,
31
31
  formData: h
@@ -47,7 +47,7 @@ var s = (s) => {
47
47
  onSubmit: x,
48
48
  className: e("flex flex-col gap-4", f),
49
49
  "data-pihanga": p,
50
- children: [l.map((e, t) => /* @__PURE__ */ a(n, {
50
+ children: [l.map((e, t) => /* @__PURE__ */ a(i, {
51
51
  cardName: e,
52
52
  parentCard: p
53
53
  }, t)), /* @__PURE__ */ a("button", {
@@ -4,6 +4,10 @@ export declare const Form: <S extends import('@pihanga2/core').ReduxState>(p: im
4
4
  export declare const PI_FORM_ACTION: {
5
5
  SUBMITTED: string;
6
6
  };
7
+ export declare const onFormSubmitted: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
+ cardID: string;
9
+ } & PiFormSubmittedEvent>) => void;
10
+ /** @deprecated Use `onFormSubmitted` instead. */
7
11
  export declare const onPiFormSubmitted: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
12
  cardID: string;
9
13
  } & PiFormSubmittedEvent>) => void;
@@ -1,7 +1,7 @@
1
1
  import { createCardDeclaration as e, createOnAction as t, registerActions as n } from "@pihanga2/core";
2
2
  //#region src/cards/form/form.types.ts
3
- var r = "pi/form", i = e(r), a = n(r, ["submitted"]), o = t(a.SUBMITTED);
3
+ var r = "pi/form", i = e(r), a = n(r, ["submitted"]), o = t(a.SUBMITTED), s = o;
4
4
  //#endregion
5
- export { i as Form, a as PI_FORM_ACTION, r as PI_FORM_CARD, o as onPiFormSubmitted };
5
+ export { i as Form, a as PI_FORM_ACTION, r as PI_FORM_CARD, o as onFormSubmitted, s as onPiFormSubmitted };
6
6
 
7
7
  //# sourceMappingURL=form.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"form.types.js","names":[],"sources":["../../../src/cards/form/form.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n type PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_FORM_CARD = \"pi/form\";\n\nexport const Form = createCardDeclaration<PiFormProps, PiFormEvents>(\n PI_FORM_CARD,\n);\n\nexport const PI_FORM_ACTION = registerActions(PI_FORM_CARD, [\"submitted\"]);\n\nexport const onPiFormSubmitted = createOnAction<PiFormSubmittedEvent>(\n PI_FORM_ACTION.SUBMITTED,\n);\n\nexport type PiFormProps = {\n /**\n * Optional id passed through to events for identification.\n */\n id?: string;\n\n /**\n * Ordered list of field card refs to render inside the form.\n * Each card (e.g. TextField, Checkbox, FormSelect) will be rendered\n * in order and wrapped by a FormContext.Provider so they can read\n * and write shared form state.\n */\n content?: PiCardRef[];\n\n /**\n * Initial values for the form fields, keyed by field name.\n */\n initialValues?: Record<string, unknown>;\n\n /**\n * Label for the submit button.\n * @default \"Submit\"\n */\n submitLabel?: string;\n\n /**\n * Additional CSS classes for the <form> element.\n */\n className?: string;\n};\n\nexport type PiFormSubmittedEvent = {\n id?: string;\n /** Snapshot of form state at the time of submission. */\n formData: Record<string, unknown>;\n};\n\nexport type PiFormEvents = {\n onSubmitted: PiFormSubmittedEvent;\n};\n"],"mappings":";;AAOA,IAAa,IAAe,WAEf,IAAO,EAClB,CACF,GAEa,IAAiB,EAAgB,GAAc,CAAC,WAAW,CAAC,GAE5D,IAAoB,EAC/B,EAAe,SACjB"}
1
+ {"version":3,"file":"form.types.js","names":[],"sources":["../../../src/cards/form/form.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n type PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_FORM_CARD = \"pi/form\";\n\nexport const Form = createCardDeclaration<PiFormProps, PiFormEvents>(\n PI_FORM_CARD,\n);\n\nexport const PI_FORM_ACTION = registerActions(PI_FORM_CARD, [\"submitted\"]);\n\nexport const onFormSubmitted = createOnAction<PiFormSubmittedEvent>(\n PI_FORM_ACTION.SUBMITTED,\n);\n\n/** @deprecated Use `onFormSubmitted` instead. */\nexport const onPiFormSubmitted = onFormSubmitted;\n\nexport type PiFormProps = {\n /**\n * Optional id passed through to events for identification.\n */\n id?: string;\n\n /**\n * Ordered list of field card refs to render inside the form.\n * Each card (e.g. TextField, Checkbox, FormSelect) will be rendered\n * in order and wrapped by a FormContext.Provider so they can read\n * and write shared form state.\n */\n content?: PiCardRef[];\n\n /**\n * Initial values for the form fields, keyed by field name.\n */\n initialValues?: Record<string, unknown>;\n\n /**\n * Label for the submit button.\n * @default \"Submit\"\n */\n submitLabel?: string;\n\n /**\n * Additional CSS classes for the <form> element.\n */\n className?: string;\n};\n\nexport type PiFormSubmittedEvent = {\n id?: string;\n /** Snapshot of form state at the time of submission. */\n formData: Record<string, unknown>;\n};\n\nexport type PiFormEvents = {\n onSubmitted: PiFormSubmittedEvent;\n};\n"],"mappings":";;AAOA,IAAa,IAAe,WAEf,IAAO,EAClB,CACF,GAEa,IAAiB,EAAgB,GAAc,CAAC,WAAW,CAAC,GAE5D,IAAkB,EAC7B,EAAe,SACjB,GAGa,IAAoB"}
@@ -1,14 +1,14 @@
1
1
  import { FormContext as e, useFormContext as t } from "./form.context.js";
2
2
  import { FormComponent as n } from "./form.component.js";
3
- import { Form as r, PI_FORM_ACTION as i, PI_FORM_CARD as a, onPiFormSubmitted as o } from "./form.types.js";
4
- import { actionTypesToEvents as s, registerCardComponent as c } from "@pihanga2/core";
3
+ import { Form as r, PI_FORM_ACTION as i, PI_FORM_CARD as a, onFormSubmitted as o, onPiFormSubmitted as s } from "./form.types.js";
4
+ import { actionTypesToEvents as c, registerCardComponent as l } from "@pihanga2/core";
5
5
  //#region src/cards/form/index.ts
6
- c({
6
+ l({
7
7
  name: a,
8
8
  component: n,
9
- events: s(i)
9
+ events: c(i)
10
10
  });
11
11
  //#endregion
12
- export { r as Form, e as FormContext, i as PI_FORM_ACTION, a as PI_FORM_CARD, o as onPiFormSubmitted, t as useFormContext };
12
+ export { r as Form, e as FormContext, i as PI_FORM_ACTION, a as PI_FORM_CARD, o as onFormSubmitted, s as onPiFormSubmitted, t as useFormContext };
13
13
 
14
14
  //# sourceMappingURL=index.js.map
@@ -1,15 +1,15 @@
1
1
  import { TooltipProvider as e } from "../../components/ui/tooltip.js";
2
2
  import { ThemeProvider as t } from "../../components/theme-provider/theme-provider.component.js";
3
- import { Card as n } from "@pihanga2/core";
4
- import { StrictMode as r } from "react";
3
+ import { StrictMode as n } from "react";
4
+ import { Card as r } from "@pihanga2/core";
5
5
  import { jsx as i } from "react/jsx-runtime";
6
6
  //#region src/cards/framework/framework.component.tsx
7
7
  var a = (a) => {
8
8
  let { page: o, theme: s = "dark", cardName: c } = a;
9
- return /* @__PURE__ */ i(r, { children: /* @__PURE__ */ i(t, {
9
+ return /* @__PURE__ */ i(n, { children: /* @__PURE__ */ i(t, {
10
10
  defaultTheme: s,
11
11
  storageKey: "shadcn-ui-theme",
12
- children: /* @__PURE__ */ i(e, { children: /* @__PURE__ */ i(n, {
12
+ children: /* @__PURE__ */ i(e, { children: /* @__PURE__ */ i(r, {
13
13
  cardName: o,
14
14
  parentCard: c
15
15
  }) })
@@ -226,6 +226,20 @@ export type GraphinTooltip = {
226
226
  * @default 4
227
227
  */
228
228
  offset?: number | [number, number];
229
+ /**
230
+ * Extra CSS class name(s) applied to the tooltip wrapper `<div>`.
231
+ * Use this to override the default background / border / shadow via
232
+ * Tailwind utilities or your own CSS classes.
233
+ *
234
+ * @example "rounded-xl shadow-lg border-primary"
235
+ */
236
+ className?: string;
237
+ /**
238
+ * Inline style overrides for the tooltip wrapper `<div>`.
239
+ * Merged on top of the built-in positioning / pointer-events styles so
240
+ * you can safely override individual properties (e.g. `padding`, `zIndex`).
241
+ */
242
+ style?: React.CSSProperties;
229
243
  };
230
244
  export type GraphinContextMenu = {
231
245
  /** Registered card name whose component is rendered inside the click panel. */
@@ -239,6 +253,20 @@ export type GraphinContextMenu = {
239
253
  * @default 4
240
254
  */
241
255
  offset?: number | [number, number];
256
+ /**
257
+ * Extra CSS class name(s) applied to the context-menu wrapper `<div>`.
258
+ * Use this to override the default background / border / shadow via
259
+ * Tailwind utilities or your own CSS classes.
260
+ *
261
+ * @example "rounded-xl shadow-lg border-primary"
262
+ */
263
+ className?: string;
264
+ /**
265
+ * Inline style overrides for the context-menu wrapper `<div>`.
266
+ * Merged on top of the built-in positioning / pointer-events styles so
267
+ * you can safely override individual properties (e.g. `padding`, `zIndex`).
268
+ */
269
+ style?: React.CSSProperties;
242
270
  };
243
271
  /**
244
272
  * Node shape types supported by G6 v5.
@@ -256,8 +284,10 @@ export type GraphinNodeStyleDef = {
256
284
  fill?: string;
257
285
  /** Border colour. */
258
286
  stroke?: string;
259
- /** Border thickness in pixels. */
287
+ /** Border thickness in pixels. Alias: `strokeWidth` (takes precedence). */
260
288
  lineWidth?: number;
289
+ /** Border thickness in pixels. Takes precedence over `lineWidth`. */
290
+ strokeWidth?: number;
261
291
  /**
262
292
  * Node size in pixels.
263
293
  * Pass a number for a square/circle; pass `[width, height]` for a rectangle.
@@ -322,10 +352,13 @@ export declare const GRAPHIN_OP_ACTION: {
322
352
  export type GraphinSetNodeStylesAction = {
323
353
  cardName: string;
324
354
  /**
325
- * Map of `nodeId` → style name (must be a key in the card's `nodeStyles` map).
326
- * @example { n1: "failed", n2: "degraded", n3: "ok" }
355
+ * Map of `nodeId` → style name or ordered list of style names to merge
356
+ * (each must be a key in the card's `nodeStyles` map).
357
+ * When an array is given, styles are merged left-to-right with later entries
358
+ * overriding duplicate properties from earlier ones.
359
+ * @example { n1: "failed", n2: ["base", "degraded"], n3: "ok" }
327
360
  */
328
- nodeStyles: Record<string, string>;
361
+ nodeStyles: Record<string, string | string[]>;
329
362
  };
330
363
  /**
331
364
  * Payload for `GRAPHIN_OP_ACTION.CLEAR_NODE_STYLES`.
@@ -1,13 +1,13 @@
1
1
  import { InputComponent as e } from "./input.component.js";
2
- import { PI_INPUT_ACTION as t, PI_INPUT_CARD as n, PiInput as r, onPiInputChanged as i, onPiInputCommitted as a } from "./input.types.js";
3
- import { actionTypesToEvents as o, registerCardComponent as s } from "@pihanga2/core";
2
+ import { PI_INPUT_ACTION as t, PI_INPUT_CARD as n, PiInput as r, onInputChanged as i, onInputCommitted as a, onPiInputChanged as o, onPiInputCommitted as s } from "./input.types.js";
3
+ import { actionTypesToEvents as c, registerCardComponent as l } from "@pihanga2/core";
4
4
  //#region src/cards/input/index.ts
5
- s({
5
+ l({
6
6
  name: n,
7
7
  component: e,
8
- events: o(t)
8
+ events: c(t)
9
9
  });
10
10
  //#endregion
11
- export { t as PI_INPUT_ACTION, n as PI_INPUT_CARD, r as PiInput, i as onPiInputChanged, a as onPiInputCommitted };
11
+ export { t as PI_INPUT_ACTION, n as PI_INPUT_CARD, r as PiInput, i as onInputChanged, a as onInputCommitted, o as onPiInputChanged, s as onPiInputCommitted };
12
12
 
13
13
  //# sourceMappingURL=index.js.map
@@ -2,6 +2,7 @@ import { useFormContext as e } from "../form/form.context.js";
2
2
  import { Label as t } from "../../components/ui/label.js";
3
3
  import { Input as n } from "../../components/ui/input.js";
4
4
  import r from "react";
5
+ import "@pihanga2/core";
5
6
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
7
  //#region src/cards/input/input.component.tsx
7
8
  var o = (o) => {
@@ -1 +1 @@
1
- {"version":3,"file":"input.component.js","names":[],"sources":["../../../src/cards/input/input.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Input} from \"@/components/ui/input\";\nimport {Label} from \"@/components/ui/label\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiInputEvents, PiInputProps} from \"./input.types\";\n\nexport const InputComponent = (\n props: PiCardProps<PiInputProps, PiInputEvents>,\n): React.ReactNode => {\n const {\n name,\n value: propValue = \"\",\n type = \"text\",\n placeholder,\n disabled,\n label,\n description,\n className,\n cardName,\n onChanged,\n onCommitted,\n } = props;\n\n // `id` and `invalid` may be injected by a parent pi/field card via\n // Pihanga's extra-prop forwarding. They are not in the official type so\n // we read them through an escape hatch.\n const injectedId = (props as {id?: string}).id;\n const invalid = Boolean((props as {invalid?: boolean}).invalid);\n\n // Detect if we are inside a pi/form card via React context.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n // Local display state — lets the user type freely without triggering Redux\n // on every keystroke. Only `onCommitted` (blur / Enter) writes back to\n // Redux, so callers that use `onCommitted` instead of `onChanged` avoid\n // per-keystroke panel rebuilds.\n const [localValue, setLocalValue] = React.useState<string>(\n type === \"file\" ? \"\" : propValue,\n );\n\n // Sync local value when the prop changes from outside (e.g. when a different\n // card is selected in the playground, resetting the controls panel).\n React.useEffect(() => {\n if (!useFormData && type !== \"file\") {\n setLocalValue(propValue);\n }\n }, [propValue, useFormData, type]);\n\n // Derive the effective value for the controlled <Input>:\n // - inside a form → read from form.formData[name]\n // - standalone → use localValue (updated on every keystroke locally)\n // - file inputs → uncontrolled (no value binding)\n const inputValue =\n type === \"file\"\n ? undefined\n : useFormData\n ? ((form.formData[name!] as string | undefined) ?? \"\")\n : localValue;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newValue =\n type === \"file\" ? (e.target.files?.[0]?.name ?? \"\") : e.target.value;\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n setLocalValue(newValue);\n onChanged({name, value: newValue});\n }\n }\n\n // Fire onCommitted when the user leaves the field or presses Enter.\n function handleBlur() {\n if (!useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Enter\" && !useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n // Use the id injected by pi/field (for label↔control linking); fall back\n // to a locally-generated id when used standalone.\n const selfId = `${cardName}-${name ?? \"input\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div data-pihanga={cardName} className=\"grid w-full gap-1.5\">\n {label && <Label htmlFor={fieldId}>{label}</Label>}\n <Input\n id={fieldId}\n type={type}\n value={inputValue}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n className={className}\n aria-invalid={invalid || undefined}\n aria-describedby={description ? `${fieldId}-desc` : undefined}\n />\n {description && (\n <p id={`${fieldId}-desc`} className=\"text-sm text-muted-foreground\">\n {description}\n </p>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;AAOA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,OAAO,IAAY,IACnB,UAAO,QACP,gBACA,aACA,UACA,gBACA,cACA,aACA,cACA,mBACE,GAKE,IAAc,EAAwB,IACtC,IAAU,EAAS,EAA8B,SAGjD,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAMvC,CAAC,GAAY,KAAiB,EAAM,SACxC,MAAS,SAAS,KAAK,CACzB;CAIA,EAAM,gBAAgB;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAc,CAAS;CAE3B,GAAG;EAAC;EAAW;EAAa;CAAI,CAAC;CAMjC,IAAM,IACJ,MAAS,SACL,KAAA,IACA,IACI,EAAK,SAAS,MAAiC,KACjD;CAER,SAAS,EAAa,GAAwC;EAC5D,IAAM,IACJ,MAAS,SAAU,EAAE,OAAO,QAAQ,IAAI,QAAQ,KAAM,EAAE,OAAO;EACjE,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAEjC,EAAc,CAAQ,GACtB,EAAU;GAAC;GAAM,OAAO;EAAQ,CAAC;CAErC;CAGA,SAAS,IAAa;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAEA,SAAS,EAAc,GAA0C;EAC/D,AAAI,EAAE,QAAQ,WAAW,CAAC,KAAe,MAAS,UAChD,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAIA,IAAM,IAAS,GAAG,EAAS,GAAG,KAAQ,WAChC,IAAU,KAAc;CAE9B,OACE,kBAAC,OAAD;EAAK,gBAAc;EAAU,WAAU;YAAvC;GACG,KAAS,kBAAC,GAAD;IAAO,SAAS;cAAU;GAAa,CAAA;GACjD,kBAAC,GAAD;IACE,IAAI;IACE;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACE;IACH;IACC;IACX,gBAAc,KAAW,KAAA;IACzB,oBAAkB,IAAc,GAAG,EAAQ,SAAS,KAAA;GACrD,CAAA;GACA,KACC,kBAAC,KAAD;IAAG,IAAI,GAAG,EAAQ;IAAQ,WAAU;cACjC;GACA,CAAA;EAEF;;AAET"}
1
+ {"version":3,"file":"input.component.js","names":[],"sources":["../../../src/cards/input/input.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Input} from \"@/components/ui/input\";\nimport {Label} from \"@/components/ui/label\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiInputEvents, PiInputProps} from \"./input.types\";\n\nexport const InputComponent = (\n props: PiCardProps<PiInputProps, PiInputEvents>,\n): React.ReactNode => {\n const {\n name,\n value: propValue = \"\",\n type = \"text\",\n placeholder,\n disabled,\n label,\n description,\n className,\n cardName,\n onChanged,\n onCommitted,\n } = props;\n\n // `id` and `invalid` may be injected by a parent pi/field card via\n // Pihanga's extra-prop forwarding. They are not in the official type so\n // we read them through an escape hatch.\n const injectedId = (props as {id?: string}).id;\n const invalid = Boolean((props as {invalid?: boolean}).invalid);\n\n // Detect if we are inside a pi/form card via React context.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n // Local display state — lets the user type freely without triggering Redux\n // on every keystroke. Only `onCommitted` (blur / Enter) writes back to\n // Redux, so callers that use `onCommitted` instead of `onChanged` avoid\n // per-keystroke panel rebuilds.\n const [localValue, setLocalValue] = React.useState<string>(\n type === \"file\" ? \"\" : propValue,\n );\n\n // Sync local value when the prop changes from outside (e.g. when a different\n // card is selected in the playground, resetting the controls panel).\n React.useEffect(() => {\n if (!useFormData && type !== \"file\") {\n setLocalValue(propValue);\n }\n }, [propValue, useFormData, type]);\n\n // Derive the effective value for the controlled <Input>:\n // - inside a form → read from form.formData[name]\n // - standalone → use localValue (updated on every keystroke locally)\n // - file inputs → uncontrolled (no value binding)\n const inputValue =\n type === \"file\"\n ? undefined\n : useFormData\n ? ((form.formData[name!] as string | undefined) ?? \"\")\n : localValue;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newValue =\n type === \"file\" ? (e.target.files?.[0]?.name ?? \"\") : e.target.value;\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n setLocalValue(newValue);\n onChanged({name, value: newValue});\n }\n }\n\n // Fire onCommitted when the user leaves the field or presses Enter.\n function handleBlur() {\n if (!useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Enter\" && !useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n // Use the id injected by pi/field (for label↔control linking); fall back\n // to a locally-generated id when used standalone.\n const selfId = `${cardName}-${name ?? \"input\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div data-pihanga={cardName} className=\"grid w-full gap-1.5\">\n {label && <Label htmlFor={fieldId}>{label}</Label>}\n <Input\n id={fieldId}\n type={type}\n value={inputValue}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n className={className}\n aria-invalid={invalid || undefined}\n aria-describedby={description ? `${fieldId}-desc` : undefined}\n />\n {description && (\n <p id={`${fieldId}-desc`} className=\"text-sm text-muted-foreground\">\n {description}\n </p>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;AAOA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,OAAO,IAAY,IACnB,UAAO,QACP,gBACA,aACA,UACA,gBACA,cACA,aACA,cACA,mBACE,GAKE,IAAc,EAAwB,IACtC,IAAU,EAAS,EAA8B,SAGjD,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAMvC,CAAC,GAAY,KAAiB,EAAM,SACxC,MAAS,SAAS,KAAK,CACzB;CAIA,EAAM,gBAAgB;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAc,CAAS;CAE3B,GAAG;EAAC;EAAW;EAAa;CAAI,CAAC;CAMjC,IAAM,IACJ,MAAS,SACL,KAAA,IACA,IACI,EAAK,SAAS,MAAiC,KACjD;CAER,SAAS,EAAa,GAAwC;EAC5D,IAAM,IACJ,MAAS,SAAU,EAAE,OAAO,QAAQ,IAAI,QAAQ,KAAM,EAAE,OAAO;EACjE,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAEjC,EAAc,CAAQ,GACtB,EAAU;GAAC;GAAM,OAAO;EAAQ,CAAC;CAErC;CAGA,SAAS,IAAa;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAEA,SAAS,EAAc,GAA0C;EAC/D,AAAI,EAAE,QAAQ,WAAW,CAAC,KAAe,MAAS,UAChD,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAIA,IAAM,IAAS,GAAG,EAAS,GAAG,KAAQ,WAChC,IAAU,KAAc;CAE9B,OACE,kBAAC,OAAD;EAAK,gBAAc;EAAU,WAAU;YAAvC;GACG,KAAS,kBAAC,GAAD;IAAO,SAAS;cAAU;GAAa,CAAA;GACjD,kBAAC,GAAD;IACE,IAAI;IACE;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACE;IACH;IACC;IACX,gBAAc,KAAW,KAAA;IACzB,oBAAkB,IAAc,GAAG,EAAQ,SAAS,KAAA;GACrD,CAAA;GACA,KACC,kBAAC,KAAD;IAAG,IAAI,GAAG,EAAQ;IAAQ,WAAU;cACjC;GACA,CAAA;EAEF;;AAET"}
@@ -4,15 +4,23 @@ export declare const PI_INPUT_ACTION: {
4
4
  CHANGED: string;
5
5
  COMMITTED: string;
6
6
  };
7
+ export declare const onInputChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
+ cardID: string;
9
+ } & PiInputChangedEvent>) => void;
10
+ /** @deprecated Use `onInputChanged` instead. */
7
11
  export declare const onPiInputChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
12
  cardID: string;
9
13
  } & PiInputChangedEvent>) => void;
10
14
  /**
11
15
  * Subscribe to "committed" events — fired when the user finishes editing
12
- * (blur or Enter key). Unlike `onChanged` (which fires on every keystroke),
13
- * `onCommitted` only fires once per editing session, making it the preferred
16
+ * (blur or Enter key). Unlike `onInputChanged` (which fires on every keystroke),
17
+ * `onInputCommitted` only fires once per editing session, making it the preferred
14
18
  * handler for controlled inputs that trigger expensive downstream work.
15
19
  */
20
+ export declare const onInputCommitted: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
21
+ cardID: string;
22
+ } & PiInputCommittedEvent>) => void;
23
+ /** @deprecated Use `onInputCommitted` instead. */
16
24
  export declare const onPiInputCommitted: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
17
25
  cardID: string;
18
26
  } & PiInputCommittedEvent>) => void;
@@ -1,7 +1,7 @@
1
1
  import { createCardDeclaration as e, createOnAction as t, registerActions as n } from "@pihanga2/core";
2
2
  //#region src/cards/input/input.types.ts
3
- var r = "pi/input", i = e(r), a = n(r, ["changed", "committed"]), o = t(a.CHANGED), s = t(a.COMMITTED);
3
+ var r = "pi/input", i = e(r), a = n(r, ["changed", "committed"]), o = t(a.CHANGED), s = o, c = t(a.COMMITTED), l = c;
4
4
  //#endregion
5
- export { a as PI_INPUT_ACTION, r as PI_INPUT_CARD, i as PiInput, o as onPiInputChanged, s as onPiInputCommitted };
5
+ export { a as PI_INPUT_ACTION, r as PI_INPUT_CARD, i as PiInput, o as onInputChanged, c as onInputCommitted, s as onPiInputChanged, l as onPiInputCommitted };
6
6
 
7
7
  //# sourceMappingURL=input.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"input.types.js","names":[],"sources":["../../../src/cards/input/input.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_INPUT_CARD = \"pi/input\";\n\nexport const PiInput = createCardDeclaration<PiInputProps, PiInputEvents>(\n PI_INPUT_CARD,\n);\n\nexport const PI_INPUT_ACTION = registerActions(PI_INPUT_CARD, [\n \"changed\",\n \"committed\",\n]);\n\nexport const onPiInputChanged = createOnAction<PiInputChangedEvent>(\n PI_INPUT_ACTION.CHANGED,\n);\n\n/**\n * Subscribe to \"committed\" events — fired when the user finishes editing\n * (blur or Enter key). Unlike `onChanged` (which fires on every keystroke),\n * `onCommitted` only fires once per editing session, making it the preferred\n * handler for controlled inputs that trigger expensive downstream work.\n */\nexport const onPiInputCommitted = createOnAction<PiInputCommittedEvent>(\n PI_INPUT_ACTION.COMMITTED,\n);\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiInputProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its value from form state and writes\n * back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled value used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n value?: string;\n\n /**\n * HTML input type.\n * Common values: \"text\" | \"email\" | \"password\" | \"number\" | \"search\" |\n * \"url\" | \"tel\" | \"date\" | \"file\".\n * Defaults to \"text\".\n */\n type?: string;\n\n /** Placeholder text shown when the input is empty. */\n placeholder?: string;\n\n /** When true, the input is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered in a `<label>` element above the input.\n * The label is automatically associated with the input via `htmlFor`.\n */\n label?: string;\n\n /**\n * Optional helper / description text rendered below the input.\n * Use this for hints, formatting guidance, or validation feedback.\n */\n description?: string;\n\n /** Extra Tailwind / CSS classes forwarded to the underlying <input> element. */\n className?: string;\n};\n\nexport type PiInputChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New value after the change. */\n value: string;\n};\n\n/**\n * Payload for the `onCommitted` event (blur / Enter key).\n * Same shape as `PiInputChangedEvent`.\n */\nexport type PiInputCommittedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** Final committed value. */\n value: string;\n};\n\nexport type PiInputEvents = {\n /** Fires on every keystroke. */\n onChanged: PiInputChangedEvent;\n /**\n * Fires once when the user finishes editing (blur or Enter key).\n * Use this instead of `onChanged` when each change triggers expensive\n * downstream work (e.g. rebuilding a panel).\n */\n onCommitted: PiInputCommittedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAgB,YAEhB,IAAU,EACrB,CACF,GAEa,IAAkB,EAAgB,GAAe,CAC5D,WACA,WACF,CAAC,GAEY,IAAmB,EAC9B,EAAgB,OAClB,GAQa,IAAqB,EAChC,EAAgB,SAClB"}
1
+ {"version":3,"file":"input.types.js","names":[],"sources":["../../../src/cards/input/input.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_INPUT_CARD = \"pi/input\";\n\nexport const PiInput = createCardDeclaration<PiInputProps, PiInputEvents>(\n PI_INPUT_CARD,\n);\n\nexport const PI_INPUT_ACTION = registerActions(PI_INPUT_CARD, [\n \"changed\",\n \"committed\",\n]);\n\nexport const onInputChanged = createOnAction<PiInputChangedEvent>(\n PI_INPUT_ACTION.CHANGED,\n);\n\n/** @deprecated Use `onInputChanged` instead. */\nexport const onPiInputChanged = onInputChanged;\n\n/**\n * Subscribe to \"committed\" events — fired when the user finishes editing\n * (blur or Enter key). Unlike `onInputChanged` (which fires on every keystroke),\n * `onInputCommitted` only fires once per editing session, making it the preferred\n * handler for controlled inputs that trigger expensive downstream work.\n */\nexport const onInputCommitted = createOnAction<PiInputCommittedEvent>(\n PI_INPUT_ACTION.COMMITTED,\n);\n\n/** @deprecated Use `onInputCommitted` instead. */\nexport const onPiInputCommitted = onInputCommitted;\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiInputProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its value from form state and writes\n * back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled value used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n value?: string;\n\n /**\n * HTML input type.\n * Common values: \"text\" | \"email\" | \"password\" | \"number\" | \"search\" |\n * \"url\" | \"tel\" | \"date\" | \"file\".\n * Defaults to \"text\".\n */\n type?: string;\n\n /** Placeholder text shown when the input is empty. */\n placeholder?: string;\n\n /** When true, the input is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered in a `<label>` element above the input.\n * The label is automatically associated with the input via `htmlFor`.\n */\n label?: string;\n\n /**\n * Optional helper / description text rendered below the input.\n * Use this for hints, formatting guidance, or validation feedback.\n */\n description?: string;\n\n /** Extra Tailwind / CSS classes forwarded to the underlying <input> element. */\n className?: string;\n};\n\nexport type PiInputChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New value after the change. */\n value: string;\n};\n\n/**\n * Payload for the `onCommitted` event (blur / Enter key).\n * Same shape as `PiInputChangedEvent`.\n */\nexport type PiInputCommittedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** Final committed value. */\n value: string;\n};\n\nexport type PiInputEvents = {\n /** Fires on every keystroke. */\n onChanged: PiInputChangedEvent;\n /**\n * Fires once when the user finishes editing (blur or Enter key).\n * Use this instead of `onChanged` when each change triggers expensive\n * downstream work (e.g. rebuilding a panel).\n */\n onCommitted: PiInputCommittedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAgB,YAEhB,IAAU,EACrB,CACF,GAEa,IAAkB,EAAgB,GAAe,CAC5D,WACA,WACF,CAAC,GAEY,IAAiB,EAC5B,EAAgB,OAClB,GAGa,IAAmB,GAQnB,IAAmB,EAC9B,EAAgB,SAClB,GAGa,IAAqB"}