@pihanga2/shadcn 0.2.1 → 0.2.2

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 (108) 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 -1
  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 +1 -1
  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.types.d.ts +1 -0
  12. package/cards/button/button.types.js.map +1 -1
  13. package/cards/{chartGraph/chartGraph.component.d.ts → chart/chart.component.d.ts} +1 -1
  14. package/cards/chart/chart.types.d.ts +223 -0
  15. package/cards/chart/index.d.ts +1 -0
  16. package/cards/checkbox/checkbox.component.js +1 -0
  17. package/cards/checkbox/checkbox.component.js.map +1 -1
  18. package/cards/checkbox/checkbox.types.d.ts +4 -0
  19. package/cards/checkbox/checkbox.types.js +2 -2
  20. package/cards/checkbox/checkbox.types.js.map +1 -1
  21. package/cards/checkbox/index.js +5 -5
  22. package/cards/conditional/conditional.types.d.ts +20 -5
  23. package/cards/conditional/conditional.types.js.map +1 -1
  24. package/cards/core-index.d.ts +3 -0
  25. package/cards/core-index.js +36 -29
  26. package/cards/dataTable/dataTable.types.js.map +1 -1
  27. package/cards/dataTable/dataTableRowDetail.component.js +1 -0
  28. package/cards/dataTable/dataTableRowDetail.component.js.map +1 -1
  29. package/cards/field/field.types.js.map +1 -1
  30. package/cards/fileDrop/fileDrop.component.js +90 -0
  31. package/cards/fileDrop/fileDrop.component.js.map +1 -0
  32. package/cards/fileDrop/fileDrop.types.js +11 -0
  33. package/cards/fileDrop/fileDrop.types.js.map +1 -0
  34. package/cards/fileDrop/index.js +13 -0
  35. package/cards/fileDrop/index.js.map +1 -0
  36. package/cards/flexGrid/flexGrid.types.js.map +1 -1
  37. package/cards/form/form.types.d.ts +4 -0
  38. package/cards/form/form.types.js +2 -2
  39. package/cards/form/form.types.js.map +1 -1
  40. package/cards/form/index.js +5 -5
  41. package/cards/graphin/graphin.types.d.ts +37 -4
  42. package/cards/input/index.js +5 -5
  43. package/cards/input/input.component.js +1 -0
  44. package/cards/input/input.component.js.map +1 -1
  45. package/cards/input/input.types.d.ts +10 -2
  46. package/cards/input/input.types.js +2 -2
  47. package/cards/input/input.types.js.map +1 -1
  48. package/cards/list/list.types.js +1 -0
  49. package/cards/list/list.types.js.map +1 -1
  50. package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +5 -7
  51. package/cards/pageWithNavbar/pageWithNavbar.component.js +1 -1
  52. package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -1
  53. package/cards/pasteTarget/pasteTarget.component.js.map +1 -1
  54. package/cards/select/index.js +5 -5
  55. package/cards/select/select.component.js +1 -0
  56. package/cards/select/select.component.js.map +1 -1
  57. package/cards/select/select.types.d.ts +12 -0
  58. package/cards/select/select.types.js +2 -2
  59. package/cards/select/select.types.js.map +1 -1
  60. package/cards/slider/index.js +13 -0
  61. package/cards/slider/index.js.map +1 -0
  62. package/cards/slider/slider.component.js +64 -0
  63. package/cards/slider/slider.component.js.map +1 -0
  64. package/cards/slider/slider.types.d.ts +12 -4
  65. package/cards/slider/slider.types.js +7 -0
  66. package/cards/slider/slider.types.js.map +1 -0
  67. package/cards/sliderValue/index.js +12 -0
  68. package/cards/sliderValue/index.js.map +1 -0
  69. package/cards/sliderValue/sliderValue.component.js +33 -0
  70. package/cards/sliderValue/sliderValue.component.js.map +1 -0
  71. package/cards/sliderValue/sliderValue.types.js +7 -0
  72. package/cards/sliderValue/sliderValue.types.js.map +1 -0
  73. package/cards/stack/stack.component.js +1 -1
  74. package/cards/stack/stack.component.js.map +1 -1
  75. package/cards/stack/stack.types.js.map +1 -1
  76. package/cards/switch/index.js +5 -5
  77. package/cards/switch/switch.component.js +1 -0
  78. package/cards/switch/switch.component.js.map +1 -1
  79. package/cards/switch/switch.types.d.ts +4 -0
  80. package/cards/switch/switch.types.js +2 -2
  81. package/cards/switch/switch.types.js.map +1 -1
  82. package/cards/textField/index.js +5 -5
  83. package/cards/textField/textField.component.js +1 -0
  84. package/cards/textField/textField.component.js.map +1 -1
  85. package/cards/textField/textField.types.d.ts +4 -0
  86. package/cards/textField/textField.types.js +2 -2
  87. package/cards/textField/textField.types.js.map +1 -1
  88. package/cards/toast/index.js +7 -7
  89. package/cards/toast/toast.component.js.map +1 -1
  90. package/cards/toast/toast.types.d.ts +4 -0
  91. package/cards/toast/toast.types.js +2 -2
  92. package/cards/toast/toast.types.js.map +1 -1
  93. package/cards/toggleGroup/index.js +5 -5
  94. package/cards/toggleGroup/toggleGroup.component.js +1 -0
  95. package/cards/toggleGroup/toggleGroup.component.js.map +1 -1
  96. package/cards/toggleGroup/toggleGroup.types.d.ts +4 -0
  97. package/cards/toggleGroup/toggleGroup.types.js +2 -2
  98. package/cards/toggleGroup/toggleGroup.types.js.map +1 -1
  99. package/cards/typography/typography.types.js +1 -0
  100. package/cards/typography/typography.types.js.map +1 -1
  101. package/components/ui/slider.js +36 -0
  102. package/components/ui/slider.js.map +1 -0
  103. package/components/ui/toggle-group.js +1 -0
  104. package/components/ui/toggle-group.js.map +1 -1
  105. package/package.json +19 -2
  106. package/pihanga-shadcn.css +1 -1
  107. package/cards/chartGraph/chartGraph.types.d.ts +0 -102
  108. package/cards/chartGraph/index.d.ts +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"toast.component.js","names":[],"sources":["../../../src/cards/toast/toast.component.tsx"],"sourcesContent":["import React, {useEffect, useRef, useState} from \"react\";\nimport {\n Card,\n type PiCardProps,\n type PiCardRef,\n usePiReducer,\n type ReduxAction,\n type ReduxState,\n} from \"@pihanga2/core\";\nimport {toast} from \"sonner\";\n\nimport {\n ShowToastEvent,\n TOAST_OP_ACTION,\n ToastPosition,\n ToastType,\n type PiToastEvents,\n type PiToastProps,\n} from \"./toast.types\";\n\nexport const ToastComponent = (\n props: PiCardProps<PiToastProps, PiToastEvents>,\n): React.ReactNode => {\n const {\n variant: defaultVariant = \"default\",\n duration: defaultDuration = 4000,\n dismissible: defaultDismissible = true,\n className: defaultClassName,\n onClosed,\n cardName,\n } = props;\n\n // State for tracking Redux-triggered toast messages\n const [currentToast, setCurrentToast] = useState<{\n message?: string;\n description?: string;\n contentCard?: PiCardRef;\n variant: ToastType;\n position?: ToastPosition;\n duration: number;\n } | null>(null);\n\n // Listen for showToast Redux messages\n // This allows triggering toasts from anywhere via dispatchShowToast\n usePiReducer<ReduxState, ShowToastEvent & ReduxAction>(\n TOAST_OP_ACTION.SHOW,\n (_, action) => {\n // Only respond if message is for this card or no specific cardName is set\n if (action.cardName && action.cardName !== cardName) {\n return;\n }\n setCurrentToast({\n message: action.message,\n description: action.description,\n contentCard: action.contentCard,\n variant: action.variant ?? defaultVariant,\n position: action.position,\n duration: action.duration ?? defaultDuration,\n });\n },\n cardName,\n );\n\n // Setup hooks before conditional rendering\n const toastIdRef = useRef<string | number | undefined>(undefined);\n\n useEffect(() => {\n // Only show toast if Redux message was received\n if (!currentToast) {\n return;\n }\n\n // Map our toast types to Sonner's toast function\n const toastFn =\n {\n success: toast.success,\n error: toast.error,\n info: toast.info,\n warning: toast.warning,\n default: toast,\n }[currentToast.variant] || toast;\n\n // Build className: combine default + variant-based class\n const className = [defaultClassName, `toast-${currentToast.variant}`]\n .filter(Boolean)\n .join(\" \");\n\n // If contentCard is provided, render it as custom JSX content\n if (currentToast.contentCard) {\n const contentCard = currentToast.contentCard;\n const CustomToastContent = () => (\n <Card cardName={contentCard} parentCard={cardName} />\n );\n\n // Show the toast with custom card content\n toastIdRef.current = toastFn(CustomToastContent, {\n duration: currentToast.duration,\n position: currentToast.position || \"bottom-right\",\n dismissible: defaultDismissible,\n className,\n onDismiss: () => {\n setCurrentToast(null);\n onClosed({});\n },\n onAutoClose: () => {\n setCurrentToast(null);\n onClosed({});\n },\n });\n } else {\n // Show the toast with message and optional description\n toastIdRef.current = toastFn(currentToast.message, {\n description: currentToast.description,\n duration: currentToast.duration,\n position: currentToast.position || \"bottom-right\",\n dismissible: defaultDismissible,\n className,\n onDismiss: () => {\n setCurrentToast(null);\n onClosed({});\n },\n onAutoClose: () => {\n setCurrentToast(null);\n onClosed({});\n },\n });\n }\n\n // Cleanup on unmount\n return () => {\n if (toastIdRef.current !== undefined) {\n toast.dismiss(toastIdRef.current);\n }\n };\n }, [currentToast, defaultDismissible, defaultClassName, onClosed, cardName]);\n\n // This component doesn't render visible DOM itself\n // Sonner renders toasts in a portal via its Toaster component\n return <div data-pihanga={cardName} style={{display: \"none\"}} />;\n};\n"],"mappings":";;;;;;AAoBA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SAAS,IAAiB,WAC1B,UAAU,IAAkB,KAC5B,aAAa,IAAqB,IAClC,WAAW,GACX,aACA,gBACE,GAGE,CAAC,GAAc,KAAmB,EAO9B,IAAI;CAId,EACE,EAAgB,OACf,GAAG,MAAW;EAET,EAAO,YAAY,EAAO,aAAa,KAG3C,EAAgB;GACd,SAAS,EAAO;GAChB,aAAa,EAAO;GACpB,aAAa,EAAO;GACpB,SAAS,EAAO,WAAW;GAC3B,UAAU,EAAO;GACjB,UAAU,EAAO,YAAY;EAC/B,CAAC;CACH,GACA,CACF;CAGA,IAAM,IAAa,EAAoC,KAAA,CAAS;CA0EhE,OAxEA,QAAgB;EAEd,IAAI,CAAC,GACH;EAIF,IAAM,IACJ;GACE,SAAS,EAAM;GACf,OAAO,EAAM;GACb,MAAM,EAAM;GACZ,SAAS,EAAM;GACf,SAAS;EACX,EAAE,EAAa,YAAY,GAGvB,IAAY,CAAC,GAAkB,SAAS,EAAa,SAAS,EACjE,OAAO,OAAO,EACd,KAAK,GAAG;EAGX,IAAI,EAAa,aAAa;GAC5B,IAAM,IAAc,EAAa;GAMjC,EAAW,UAAU,QAJnB,kBAAC,GAAD;IAAM,UAAU;IAAa,YAAY;GAAW,CAAA,GAIL;IAC/C,UAAU,EAAa;IACvB,UAAU,EAAa,YAAY;IACnC,aAAa;IACb;IACA,iBAAiB;KAEf,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;IACb;IACA,mBAAmB;KAEjB,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;IACb;GACF,CAAC;EACH,OAEE,EAAW,UAAU,EAAQ,EAAa,SAAS;GACjD,aAAa,EAAa;GAC1B,UAAU,EAAa;GACvB,UAAU,EAAa,YAAY;GACnC,aAAa;GACb;GACA,iBAAiB;IAEf,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;GACb;GACA,mBAAmB;IAEjB,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;GACb;EACF,CAAC;EAIH,aAAa;GACX,AAAI,EAAW,YAAY,KAAA,KACzB,EAAM,QAAQ,EAAW,OAAO;EAEpC;CACF,GAAG;EAAC;EAAc;EAAoB;EAAkB;EAAU;CAAQ,CAAC,GAIpE,kBAAC,OAAD;EAAK,gBAAc;EAAU,OAAO,EAAC,SAAS,OAAM;CAAI,CAAA;AACjE"}
1
+ {"version":3,"file":"toast.component.js","names":[],"sources":["../../../src/cards/toast/toast.component.tsx"],"sourcesContent":["import React, {useEffect, useRef, useState} from \"react\";\nimport {\n Card,\n type PiCardProps,\n type PiCardRef,\n usePiReducer,\n type ReduxAction,\n type ReduxState,\n} from \"@pihanga2/core\";\nimport {toast} from \"sonner\";\n\nimport {\n type ShowToastEvent,\n TOAST_OP_ACTION,\n type ToastPosition,\n type ToastType,\n type PiToastEvents,\n type PiToastProps,\n} from \"./toast.types\";\n\nexport const ToastComponent = (\n props: PiCardProps<PiToastProps, PiToastEvents>,\n): React.ReactNode => {\n const {\n variant: defaultVariant = \"default\",\n duration: defaultDuration = 4000,\n dismissible: defaultDismissible = true,\n className: defaultClassName,\n onClosed,\n cardName,\n } = props;\n\n // State for tracking Redux-triggered toast messages\n const [currentToast, setCurrentToast] = useState<{\n message?: string;\n description?: string;\n contentCard?: PiCardRef;\n variant: ToastType;\n position?: ToastPosition;\n duration: number;\n } | null>(null);\n\n // Listen for showToast Redux messages\n // This allows triggering toasts from anywhere via dispatchShowToast\n usePiReducer<ReduxState, ShowToastEvent & ReduxAction>(\n TOAST_OP_ACTION.SHOW,\n (_, action) => {\n // Only respond if message is for this card or no specific cardName is set\n if (action.cardName && action.cardName !== cardName) {\n return;\n }\n setCurrentToast({\n message: action.message,\n description: action.description,\n contentCard: action.contentCard,\n variant: action.variant ?? defaultVariant,\n position: action.position,\n duration: action.duration ?? defaultDuration,\n });\n },\n cardName,\n );\n\n // Setup hooks before conditional rendering\n const toastIdRef = useRef<string | number | undefined>(undefined);\n\n useEffect(() => {\n // Only show toast if Redux message was received\n if (!currentToast) {\n return;\n }\n\n // Map our toast types to Sonner's toast function\n const toastFn =\n {\n success: toast.success,\n error: toast.error,\n info: toast.info,\n warning: toast.warning,\n default: toast,\n }[currentToast.variant] || toast;\n\n // Build className: combine default + variant-based class\n const className = [defaultClassName, `toast-${currentToast.variant}`]\n .filter(Boolean)\n .join(\" \");\n\n // If contentCard is provided, render it as custom JSX content\n if (currentToast.contentCard) {\n const contentCard = currentToast.contentCard;\n const CustomToastContent = () => (\n <Card cardName={contentCard} parentCard={cardName} />\n );\n\n // Show the toast with custom card content\n toastIdRef.current = toastFn(CustomToastContent, {\n duration: currentToast.duration,\n position: currentToast.position || \"bottom-right\",\n dismissible: defaultDismissible,\n className,\n onDismiss: () => {\n setCurrentToast(null);\n onClosed({});\n },\n onAutoClose: () => {\n setCurrentToast(null);\n onClosed({});\n },\n });\n } else {\n // Show the toast with message and optional description\n toastIdRef.current = toastFn(currentToast.message, {\n description: currentToast.description,\n duration: currentToast.duration,\n position: currentToast.position || \"bottom-right\",\n dismissible: defaultDismissible,\n className,\n onDismiss: () => {\n setCurrentToast(null);\n onClosed({});\n },\n onAutoClose: () => {\n setCurrentToast(null);\n onClosed({});\n },\n });\n }\n\n // Cleanup on unmount\n return () => {\n if (toastIdRef.current !== undefined) {\n toast.dismiss(toastIdRef.current);\n }\n };\n }, [currentToast, defaultDismissible, defaultClassName, onClosed, cardName]);\n\n // This component doesn't render visible DOM itself\n // Sonner renders toasts in a portal via its Toaster component\n return <div data-pihanga={cardName} style={{display: \"none\"}} />;\n};\n"],"mappings":";;;;;;AAoBA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SAAS,IAAiB,WAC1B,UAAU,IAAkB,KAC5B,aAAa,IAAqB,IAClC,WAAW,GACX,aACA,gBACE,GAGE,CAAC,GAAc,KAAmB,EAO9B,IAAI;CAId,EACE,EAAgB,OACf,GAAG,MAAW;EAET,EAAO,YAAY,EAAO,aAAa,KAG3C,EAAgB;GACd,SAAS,EAAO;GAChB,aAAa,EAAO;GACpB,aAAa,EAAO;GACpB,SAAS,EAAO,WAAW;GAC3B,UAAU,EAAO;GACjB,UAAU,EAAO,YAAY;EAC/B,CAAC;CACH,GACA,CACF;CAGA,IAAM,IAAa,EAAoC,KAAA,CAAS;CA0EhE,OAxEA,QAAgB;EAEd,IAAI,CAAC,GACH;EAIF,IAAM,IACJ;GACE,SAAS,EAAM;GACf,OAAO,EAAM;GACb,MAAM,EAAM;GACZ,SAAS,EAAM;GACf,SAAS;EACX,EAAE,EAAa,YAAY,GAGvB,IAAY,CAAC,GAAkB,SAAS,EAAa,SAAS,EACjE,OAAO,OAAO,EACd,KAAK,GAAG;EAGX,IAAI,EAAa,aAAa;GAC5B,IAAM,IAAc,EAAa;GAMjC,EAAW,UAAU,QAJnB,kBAAC,GAAD;IAAM,UAAU;IAAa,YAAY;GAAW,CAAA,GAIL;IAC/C,UAAU,EAAa;IACvB,UAAU,EAAa,YAAY;IACnC,aAAa;IACb;IACA,iBAAiB;KAEf,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;IACb;IACA,mBAAmB;KAEjB,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;IACb;GACF,CAAC;EACH,OAEE,EAAW,UAAU,EAAQ,EAAa,SAAS;GACjD,aAAa,EAAa;GAC1B,UAAU,EAAa;GACvB,UAAU,EAAa,YAAY;GACnC,aAAa;GACb;GACA,iBAAiB;IAEf,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;GACb;GACA,mBAAmB;IAEjB,AADA,EAAgB,IAAI,GACpB,EAAS,CAAC,CAAC;GACb;EACF,CAAC;EAIH,aAAa;GACX,AAAI,EAAW,YAAY,KAAA,KACzB,EAAM,QAAQ,EAAW,OAAO;EAEpC;CACF,GAAG;EAAC;EAAc;EAAoB;EAAkB;EAAU;CAAQ,CAAC,GAIpE,kBAAC,OAAD;EAAK,gBAAc;EAAU,OAAO,EAAC,SAAS,OAAM;CAAI,CAAA;AACjE"}
@@ -44,6 +44,10 @@ export declare const onShowToast: <S extends import('@pihanga2/core').ReduxState
44
44
  export declare const PI_TOAST_ACTION: {
45
45
  CLOSED: string;
46
46
  };
47
+ export declare const onToastClosed: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
48
+ cardID: string;
49
+ } & PiToastClosedEvent>) => void;
50
+ /** @deprecated Use `onToastClosed` instead. */
47
51
  export declare const onPiToastClosed: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
48
52
  cardID: string;
49
53
  } & PiToastClosedEvent>) => void;
@@ -5,8 +5,8 @@ var r = "pi/toast", i = e(r), a = n("toast/op", ["show"]), o = (e, t) => {
5
5
  ...t,
6
6
  type: a.SHOW
7
7
  });
8
- }, s = t(a.SHOW), c = n(r, ["closed"]), l = t(c.CLOSED);
8
+ }, s = t(a.SHOW), c = n(r, ["closed"]), l = t(c.CLOSED), u = l;
9
9
  //#endregion
10
- export { c as PI_TOAST_ACTION, r as PI_TOAST_CARD, a as TOAST_OP_ACTION, i as Toast, o as dispatchShowToast, l as onPiToastClosed, s as onShowToast };
10
+ export { c as PI_TOAST_ACTION, r as PI_TOAST_CARD, a as TOAST_OP_ACTION, i as Toast, o as dispatchShowToast, u as onPiToastClosed, s as onShowToast, l as onToastClosed };
11
11
 
12
12
  //# sourceMappingURL=toast.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast.types.js","names":[],"sources":["../../../src/cards/toast/toast.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n PiCardRef,\n registerActions,\n type DispatchF,\n} from \"@pihanga2/core\";\n\nexport const PI_TOAST_CARD = \"pi/toast\";\n\nexport const Toast = createCardDeclaration<PiToastProps, PiToastEvents>(\n PI_TOAST_CARD,\n);\n\nexport const TOAST_OP_ACTION = registerActions(\"toast/op\", [\"show\"]);\n\n/**\n * Dispatch helper to show a toast\n *\n * @param d - Dispatch function from Pihanga\n * @param ev - Toast event data\n *\n * @example\n * ```typescript\n * import {dispatchShowToast} from \"@/cards/toast\";\n *\n * dispatchShowToast(_dispatch, {\n * message: \"Success!\",\n * description: \"Your changes were saved.\",\n * variant: \"success\",\n * duration: 3000,\n * });\n * ```\n */\nexport const dispatchShowToast = (d: DispatchF, ev: ShowToastEvent) => {\n d({...ev, type: TOAST_OP_ACTION.SHOW});\n};\n\n/**\n * Action handler for when a toast is shown\n *\n * Use this in your reducers or effects to handle toast display events:\n *\n * @example\n * ```typescript\n * import {onShowToast} from \"@/cards/toast\";\n *\n * export const handleShowToast = onShowToast((state, action) => {\n * console.log(\"Toast shown:\", action.payload.message);\n * return state;\n * });\n * ```\n */\nexport const onShowToast = createOnAction<ShowToastEvent>(TOAST_OP_ACTION.SHOW);\n\nexport const PI_TOAST_ACTION = registerActions(PI_TOAST_CARD, [\"closed\"]);\n\nexport const onPiToastClosed = createOnAction<PiToastClosedEvent>(\n PI_TOAST_ACTION.CLOSED,\n);\n\n/**\n * Toast notification type/variant.\n */\nexport type ToastType = \"default\" | \"success\" | \"error\" | \"info\" | \"warning\";\n\n/**\n * Position of the toast on the screen.\n */\nexport type ToastPosition =\n | \"top-left\"\n | \"top-center\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-center\"\n | \"bottom-right\";\n\nexport type PiToastProps = {\n /**\n * Default variant for toasts shown by this card instance.\n * Can be overridden per individual toast via ShowToastEvent.variant.\n * @default 'default'\n */\n variant?: ToastType;\n\n /**\n * Default duration in milliseconds before the toast auto-closes.\n * Can be overridden per individual toast via ShowToastEvent.duration.\n * Set to `Infinity` to disable auto-close.\n * @default 4000\n */\n duration?: number;\n\n /**\n * Whether toasts from this card are dismissible by the user.\n * This is a card-level setting only; it cannot be overridden per individual toast.\n * @default true\n */\n dismissible?: boolean;\n\n /**\n * Custom CSS class to apply to all toasts from this card.\n */\n className?: string;\n};\n\nexport type PiToastClosedEvent = {\n id?: string;\n};\n\nexport type PiToastEvents = {\n onClosed: PiToastClosedEvent;\n};\n\n/**\n * Event payload for showing a toast\n */\nexport type ShowToastEvent = {\n cardName?: string;\n message: string;\n description?: string;\n contentCard?: PiCardRef; // Alternative: custom card for richer content\n variant?: ToastType;\n position?: ToastPosition; // Toast position on screen\n duration?: number;\n};\n"],"mappings":";;AAQA,IAAa,IAAgB,YAEhB,IAAQ,EACnB,CACF,GAEa,IAAkB,EAAgB,YAAY,CAAC,MAAM,CAAC,GAoBtD,KAAqB,GAAc,MAAuB;CACrE,EAAE;EAAC,GAAG;EAAI,MAAM,EAAgB;CAAI,CAAC;AACvC,GAiBa,IAAc,EAA+B,EAAgB,IAAI,GAEjE,IAAkB,EAAgB,GAAe,CAAC,QAAQ,CAAC,GAE3D,IAAkB,EAC7B,EAAgB,MAClB"}
1
+ {"version":3,"file":"toast.types.js","names":[],"sources":["../../../src/cards/toast/toast.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n type PiCardRef,\n registerActions,\n type DispatchF,\n} from \"@pihanga2/core\";\n\nexport const PI_TOAST_CARD = \"pi/toast\";\n\nexport const Toast = createCardDeclaration<PiToastProps, PiToastEvents>(\n PI_TOAST_CARD,\n);\n\nexport const TOAST_OP_ACTION = registerActions(\"toast/op\", [\"show\"]);\n\n/**\n * Dispatch helper to show a toast\n *\n * @param d - Dispatch function from Pihanga\n * @param ev - Toast event data\n *\n * @example\n * ```typescript\n * import {dispatchShowToast} from \"@/cards/toast\";\n *\n * dispatchShowToast(_dispatch, {\n * message: \"Success!\",\n * description: \"Your changes were saved.\",\n * variant: \"success\",\n * duration: 3000,\n * });\n * ```\n */\nexport const dispatchShowToast = (d: DispatchF, ev: ShowToastEvent) => {\n d({...ev, type: TOAST_OP_ACTION.SHOW});\n};\n\n/**\n * Action handler for when a toast is shown\n *\n * Use this in your reducers or effects to handle toast display events:\n *\n * @example\n * ```typescript\n * import {onShowToast} from \"@/cards/toast\";\n *\n * export const handleShowToast = onShowToast((state, action) => {\n * console.log(\"Toast shown:\", action.payload.message);\n * return state;\n * });\n * ```\n */\nexport const onShowToast = createOnAction<ShowToastEvent>(TOAST_OP_ACTION.SHOW);\n\nexport const PI_TOAST_ACTION = registerActions(PI_TOAST_CARD, [\"closed\"]);\n\nexport const onToastClosed = createOnAction<PiToastClosedEvent>(\n PI_TOAST_ACTION.CLOSED,\n);\n\n/** @deprecated Use `onToastClosed` instead. */\nexport const onPiToastClosed = onToastClosed;\n\n/**\n * Toast notification type/variant.\n */\nexport type ToastType = \"default\" | \"success\" | \"error\" | \"info\" | \"warning\";\n\n/**\n * Position of the toast on the screen.\n */\nexport type ToastPosition =\n | \"top-left\"\n | \"top-center\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-center\"\n | \"bottom-right\";\n\nexport type PiToastProps = {\n /**\n * Default variant for toasts shown by this card instance.\n * Can be overridden per individual toast via ShowToastEvent.variant.\n * @default 'default'\n */\n variant?: ToastType;\n\n /**\n * Default duration in milliseconds before the toast auto-closes.\n * Can be overridden per individual toast via ShowToastEvent.duration.\n * Set to `Infinity` to disable auto-close.\n * @default 4000\n */\n duration?: number;\n\n /**\n * Whether toasts from this card are dismissible by the user.\n * This is a card-level setting only; it cannot be overridden per individual toast.\n * @default true\n */\n dismissible?: boolean;\n\n /**\n * Custom CSS class to apply to all toasts from this card.\n */\n className?: string;\n};\n\nexport type PiToastClosedEvent = {\n id?: string;\n};\n\nexport type PiToastEvents = {\n onClosed: PiToastClosedEvent;\n};\n\n/**\n * Event payload for showing a toast\n */\nexport type ShowToastEvent = {\n cardName?: string;\n message: string;\n description?: string;\n contentCard?: PiCardRef; // Alternative: custom card for richer content\n variant?: ToastType;\n position?: ToastPosition; // Toast position on screen\n duration?: number;\n};\n"],"mappings":";;AAQA,IAAa,IAAgB,YAEhB,IAAQ,EACnB,CACF,GAEa,IAAkB,EAAgB,YAAY,CAAC,MAAM,CAAC,GAoBtD,KAAqB,GAAc,MAAuB;CACrE,EAAE;EAAC,GAAG;EAAI,MAAM,EAAgB;CAAI,CAAC;AACvC,GAiBa,IAAc,EAA+B,EAAgB,IAAI,GAEjE,IAAkB,EAAgB,GAAe,CAAC,QAAQ,CAAC,GAE3D,IAAgB,EAC3B,EAAgB,MAClB,GAGa,IAAkB"}
@@ -1,13 +1,13 @@
1
1
  import { ToggleGroupComponent as e } from "./toggleGroup.component.js";
2
- import { PI_TOGGLE_GROUP_ACTION as t, PI_TOGGLE_GROUP_CARD as n, ToggleGroup as r, onPiToggleGroupChanged as i } from "./toggleGroup.types.js";
3
- import { actionTypesToEvents as a, registerCardComponent as o } from "@pihanga2/core";
2
+ import { PI_TOGGLE_GROUP_ACTION as t, PI_TOGGLE_GROUP_CARD as n, ToggleGroup as r, onPiToggleGroupChanged as i, onToggleGroupChanged as a } from "./toggleGroup.types.js";
3
+ import { actionTypesToEvents as o, registerCardComponent as s } from "@pihanga2/core";
4
4
  //#region src/cards/toggleGroup/index.ts
5
- o({
5
+ s({
6
6
  name: n,
7
7
  component: e,
8
- events: a(t)
8
+ events: o(t)
9
9
  });
10
10
  //#endregion
11
- export { t as PI_TOGGLE_GROUP_ACTION, n as PI_TOGGLE_GROUP_CARD, r as ToggleGroup, i as onPiToggleGroupChanged };
11
+ export { t as PI_TOGGLE_GROUP_ACTION, n as PI_TOGGLE_GROUP_CARD, r as ToggleGroup, i as onPiToggleGroupChanged, a as onToggleGroupChanged };
12
12
 
13
13
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,6 @@
1
1
  import { useFormContext as e } from "../form/form.context.js";
2
2
  import { ToggleGroup as t, ToggleGroupItem as n } from "../../components/ui/toggle-group.js";
3
+ import "@pihanga2/core";
3
4
  import r from "react";
4
5
  import { jsx as i } from "react/jsx-runtime";
5
6
  //#region src/cards/toggleGroup/toggleGroup.component.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"toggleGroup.component.js","names":[],"sources":["../../../src/cards/toggleGroup/toggleGroup.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {\n ToggleGroup as ToggleGroupUI,\n ToggleGroupItem,\n} from \"@/components/ui/toggle-group\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {\n PiToggleGroupEvents,\n PiToggleGroupProps,\n} from \"./toggleGroup.types\";\n\nexport const ToggleGroupComponent = (\n props: PiCardProps<PiToggleGroupProps, PiToggleGroupEvents>,\n): React.ReactNode => {\n const {\n name,\n items,\n type = \"single\",\n value: propValue,\n selfManaged = false,\n variant = \"default\",\n size = \"default\",\n spacing = 0,\n disabled,\n className,\n cardName,\n onChanged,\n } = props;\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 // ---------------------------------------------------------------------------\n // Self-managed (internal) state — only active when selfManaged=true and we\n // are NOT inside a pi/form card.\n // ---------------------------------------------------------------------------\n const initialSelfValue: string | string[] =\n type === \"multiple\"\n ? Array.isArray(propValue)\n ? propValue\n : propValue != null\n ? [String(propValue)]\n : []\n : typeof propValue === \"string\"\n ? propValue\n : \"\";\n\n const [internalValue, setInternalValue] = React.useState<string | string[]>(\n initialSelfValue,\n );\n\n // ---------------------------------------------------------------------------\n // Derive the effective value from the appropriate source.\n // 1. Form context (highest priority)\n // 2. Self-managed internal state\n // 3. Externally controlled prop value\n // ---------------------------------------------------------------------------\n const formRawValue = useFormData ? form.formData[name!] : undefined;\n const value: string | string[] = useFormData\n ? type === \"multiple\"\n ? Array.isArray(formRawValue)\n ? (formRawValue as string[])\n : formRawValue != null\n ? [String(formRawValue)]\n : []\n : formRawValue != null\n ? String(formRawValue)\n : \"\"\n : selfManaged\n ? internalValue\n : (propValue ?? (type === \"multiple\" ? [] : \"\"));\n\n function handleSingleChange(newValue: string) {\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n if (selfManaged) {\n setInternalValue(newValue);\n }\n onChanged({name: name ?? cardName, value: newValue});\n }\n }\n\n function handleMultipleChange(newValue: string[]) {\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n if (selfManaged) {\n setInternalValue(newValue);\n }\n onChanged({name: name ?? cardName, value: newValue});\n }\n }\n\n // Render single-selection group\n if (type === \"single\") {\n return (\n <ToggleGroupUI\n data-pihanga={cardName}\n type=\"single\"\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={handleSingleChange}\n variant={variant}\n size={size}\n spacing={spacing}\n disabled={disabled}\n className={className}\n >\n {items.map((item) => (\n <ToggleGroupItem\n key={item.value}\n value={item.value}\n disabled={item.disabled}\n >\n {item.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroupUI>\n );\n }\n\n // Render multiple-selection group\n return (\n <ToggleGroupUI\n data-pihanga={cardName}\n type=\"multiple\"\n value={Array.isArray(value) ? value : value ? [value] : []}\n onValueChange={handleMultipleChange}\n variant={variant}\n size={size}\n spacing={spacing}\n disabled={disabled}\n className={className}\n >\n {items.map((item) => (\n <ToggleGroupItem\n key={item.value}\n value={item.value}\n disabled={item.disabled}\n >\n {item.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroupUI>\n );\n};\n"],"mappings":";;;;;AAYA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,UACA,UAAO,UACP,OAAO,GACP,iBAAc,IACd,aAAU,WACV,UAAO,WACP,aAAU,GACV,aACA,cACA,aACA,iBACE,GAGE,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAMvC,IACJ,MAAS,aACL,MAAM,QAAQ,CAAS,IACrB,IACA,KAAa,OAEX,CAAC,IADD,CAAC,OAAO,CAAS,CAAC,IAEtB,OAAO,KAAc,WACnB,IACA,IAEF,CAAC,GAAe,KAAoB,EAAM,SAC9C,CACF,GAQM,IAAe,IAAc,EAAK,SAAS,KAAS,KAAA,GACpD,IAA2B,IAC7B,MAAS,aACP,MAAM,QAAQ,CAAY,IACvB,IACD,KAAgB,OAEd,CAAC,IADD,CAAC,OAAO,CAAY,CAAC,IAEzB,KAAgB,OAEd,KADA,OAAO,CAAY,IAEvB,IACE,IACC,MAAc,MAAS,aAAa,CAAC,IAAI;CAEhD,SAAS,EAAmB,GAAkB;EAC5C,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAE7B,KACF,EAAiB,CAAQ,GAE3B,EAAU;GAAC,MAAM,KAAQ;GAAU,OAAO;EAAQ,CAAC;CAEvD;CAEA,SAAS,EAAqB,GAAoB;EAChD,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAE7B,KACF,EAAiB,CAAQ,GAE3B,EAAU;GAAC,MAAM,KAAQ;GAAU,OAAO;EAAQ,CAAC;CAEvD;CA8BA,OA3BI,MAAS,WAET,kBAAC,GAAD;EACE,gBAAc;EACd,MAAK;EACL,OAAO,OAAO,KAAU,WAAW,IAAQ;EAC3C,eAAe;EACN;EACH;EACG;EACC;EACC;YAEV,EAAM,KAAK,MACV,kBAAC,GAAD;GAEE,OAAO,EAAK;GACZ,UAAU,EAAK;aAEd,EAAK;EACS,GALV,EAAK,KAKK,CAClB;CACY,CAAA,IAMjB,kBAAC,GAAD;EACE,gBAAc;EACd,MAAK;EACL,OAAO,MAAM,QAAQ,CAAK,IAAI,IAAQ,IAAQ,CAAC,CAAK,IAAI,CAAC;EACzD,eAAe;EACN;EACH;EACG;EACC;EACC;YAEV,EAAM,KAAK,MACV,kBAAC,GAAD;GAEE,OAAO,EAAK;GACZ,UAAU,EAAK;aAEd,EAAK;EACS,GALV,EAAK,KAKK,CAClB;CACY,CAAA;AAEnB"}
1
+ {"version":3,"file":"toggleGroup.component.js","names":[],"sources":["../../../src/cards/toggleGroup/toggleGroup.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {\n ToggleGroup as ToggleGroupUI,\n ToggleGroupItem,\n} from \"@/components/ui/toggle-group\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {\n PiToggleGroupEvents,\n PiToggleGroupProps,\n} from \"./toggleGroup.types\";\n\nexport const ToggleGroupComponent = (\n props: PiCardProps<PiToggleGroupProps, PiToggleGroupEvents>,\n): React.ReactNode => {\n const {\n name,\n items,\n type = \"single\",\n value: propValue,\n selfManaged = false,\n variant = \"default\",\n size = \"default\",\n spacing = 0,\n disabled,\n className,\n cardName,\n onChanged,\n } = props;\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 // ---------------------------------------------------------------------------\n // Self-managed (internal) state — only active when selfManaged=true and we\n // are NOT inside a pi/form card.\n // ---------------------------------------------------------------------------\n const initialSelfValue: string | string[] =\n type === \"multiple\"\n ? Array.isArray(propValue)\n ? propValue\n : propValue != null\n ? [String(propValue)]\n : []\n : typeof propValue === \"string\"\n ? propValue\n : \"\";\n\n const [internalValue, setInternalValue] = React.useState<string | string[]>(\n initialSelfValue,\n );\n\n // ---------------------------------------------------------------------------\n // Derive the effective value from the appropriate source.\n // 1. Form context (highest priority)\n // 2. Self-managed internal state\n // 3. Externally controlled prop value\n // ---------------------------------------------------------------------------\n const formRawValue = useFormData ? form.formData[name!] : undefined;\n const value: string | string[] = useFormData\n ? type === \"multiple\"\n ? Array.isArray(formRawValue)\n ? (formRawValue as string[])\n : formRawValue != null\n ? [String(formRawValue)]\n : []\n : formRawValue != null\n ? String(formRawValue)\n : \"\"\n : selfManaged\n ? internalValue\n : (propValue ?? (type === \"multiple\" ? [] : \"\"));\n\n function handleSingleChange(newValue: string) {\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n if (selfManaged) {\n setInternalValue(newValue);\n }\n onChanged({name: name ?? cardName, value: newValue});\n }\n }\n\n function handleMultipleChange(newValue: string[]) {\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n if (selfManaged) {\n setInternalValue(newValue);\n }\n onChanged({name: name ?? cardName, value: newValue});\n }\n }\n\n // Render single-selection group\n if (type === \"single\") {\n return (\n <ToggleGroupUI\n data-pihanga={cardName}\n type=\"single\"\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={handleSingleChange}\n variant={variant}\n size={size}\n spacing={spacing}\n disabled={disabled}\n className={className}\n >\n {items.map((item) => (\n <ToggleGroupItem\n key={item.value}\n value={item.value}\n disabled={item.disabled}\n >\n {item.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroupUI>\n );\n }\n\n // Render multiple-selection group\n return (\n <ToggleGroupUI\n data-pihanga={cardName}\n type=\"multiple\"\n value={Array.isArray(value) ? value : value ? [value] : []}\n onValueChange={handleMultipleChange}\n variant={variant}\n size={size}\n spacing={spacing}\n disabled={disabled}\n className={className}\n >\n {items.map((item) => (\n <ToggleGroupItem\n key={item.value}\n value={item.value}\n disabled={item.disabled}\n >\n {item.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroupUI>\n );\n};\n"],"mappings":";;;;;;AAYA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,UACA,UAAO,UACP,OAAO,GACP,iBAAc,IACd,aAAU,WACV,UAAO,WACP,aAAU,GACV,aACA,cACA,aACA,iBACE,GAGE,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAMvC,IACJ,MAAS,aACL,MAAM,QAAQ,CAAS,IACrB,IACA,KAAa,OAEX,CAAC,IADD,CAAC,OAAO,CAAS,CAAC,IAEtB,OAAO,KAAc,WACnB,IACA,IAEF,CAAC,GAAe,KAAoB,EAAM,SAC9C,CACF,GAQM,IAAe,IAAc,EAAK,SAAS,KAAS,KAAA,GACpD,IAA2B,IAC7B,MAAS,aACP,MAAM,QAAQ,CAAY,IACvB,IACD,KAAgB,OAEd,CAAC,IADD,CAAC,OAAO,CAAY,CAAC,IAEzB,KAAgB,OAEd,KADA,OAAO,CAAY,IAEvB,IACE,IACC,MAAc,MAAS,aAAa,CAAC,IAAI;CAEhD,SAAS,EAAmB,GAAkB;EAC5C,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAE7B,KACF,EAAiB,CAAQ,GAE3B,EAAU;GAAC,MAAM,KAAQ;GAAU,OAAO;EAAQ,CAAC;CAEvD;CAEA,SAAS,EAAqB,GAAoB;EAChD,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAE7B,KACF,EAAiB,CAAQ,GAE3B,EAAU;GAAC,MAAM,KAAQ;GAAU,OAAO;EAAQ,CAAC;CAEvD;CA8BA,OA3BI,MAAS,WAET,kBAAC,GAAD;EACE,gBAAc;EACd,MAAK;EACL,OAAO,OAAO,KAAU,WAAW,IAAQ;EAC3C,eAAe;EACN;EACH;EACG;EACC;EACC;YAEV,EAAM,KAAK,MACV,kBAAC,GAAD;GAEE,OAAO,EAAK;GACZ,UAAU,EAAK;aAEd,EAAK;EACS,GALV,EAAK,KAKK,CAClB;CACY,CAAA,IAMjB,kBAAC,GAAD;EACE,gBAAc;EACd,MAAK;EACL,OAAO,MAAM,QAAQ,CAAK,IAAI,IAAQ,IAAQ,CAAC,CAAK,IAAI,CAAC;EACzD,eAAe;EACN;EACH;EACG;EACC;EACC;YAEV,EAAM,KAAK,MACV,kBAAC,GAAD;GAEE,OAAO,EAAK;GACZ,UAAU,EAAK;aAEd,EAAK;EACS,GALV,EAAK,KAKK,CAClB;CACY,CAAA;AAEnB"}
@@ -3,6 +3,10 @@ export declare const ToggleGroup: <S extends import('@pihanga2/core').ReduxState
3
3
  export declare const PI_TOGGLE_GROUP_ACTION: {
4
4
  CHANGED: string;
5
5
  };
6
+ export declare const onToggleGroupChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
7
+ cardID: string;
8
+ } & PiToggleGroupChangedEvent>) => void;
9
+ /** @deprecated Use `onToggleGroupChanged` instead. */
6
10
  export declare const onPiToggleGroupChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
7
11
  cardID: string;
8
12
  } & PiToggleGroupChangedEvent>) => 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/toggleGroup/toggleGroup.types.ts
3
- var r = "pi/toggle-group", i = e(r), a = n(r, ["changed"]), o = t(a.CHANGED);
3
+ var r = "pi/toggle-group", i = e(r), a = n(r, ["changed"]), o = t(a.CHANGED), s = o;
4
4
  //#endregion
5
- export { a as PI_TOGGLE_GROUP_ACTION, r as PI_TOGGLE_GROUP_CARD, i as ToggleGroup, o as onPiToggleGroupChanged };
5
+ export { a as PI_TOGGLE_GROUP_ACTION, r as PI_TOGGLE_GROUP_CARD, i as ToggleGroup, s as onPiToggleGroupChanged, o as onToggleGroupChanged };
6
6
 
7
7
  //# sourceMappingURL=toggleGroup.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toggleGroup.types.js","names":[],"sources":["../../../src/cards/toggleGroup/toggleGroup.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_TOGGLE_GROUP_CARD = \"pi/toggle-group\";\n\nexport const ToggleGroup = createCardDeclaration<\n PiToggleGroupProps,\n PiToggleGroupEvents\n>(PI_TOGGLE_GROUP_CARD);\n\nexport const PI_TOGGLE_GROUP_ACTION = registerActions(PI_TOGGLE_GROUP_CARD, [\n \"changed\",\n]);\n\nexport const onPiToggleGroupChanged = createOnAction<PiToggleGroupChangedEvent>(\n PI_TOGGLE_GROUP_ACTION.CHANGED,\n);\n\n// ---------------------------------------------------------------------------\n// Item type\n// ---------------------------------------------------------------------------\n\nexport type PiToggleGroupItem = {\n /** The value associated with this toggle item. */\n value: string;\n /** Human-readable label rendered inside the toggle button. */\n label: string;\n /** When true, this individual item is disabled. */\n disabled?: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiToggleGroupProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its selected value from form data and\n * writes back via form.handleChange.\n */\n name?: string;\n\n /**\n * The list of toggle items to display.\n */\n items: PiToggleGroupItem[];\n\n /**\n * Selection mode.\n * - `\"single\"` — at most one item can be active at a time.\n * - `\"multiple\"` — any number of items can be active simultaneously.\n *\n * @default \"single\"\n */\n type?: \"single\" | \"multiple\";\n\n /**\n * Controlled selected value(s).\n * - In `\"single\"` mode: a `string` (or `undefined` for nothing selected).\n * - In `\"multiple\"` mode: an array of `string`.\n *\n * Ignored when `name` is set and the component is inside a pi/form.\n * Also ignored when `selfManaged` is `true`.\n */\n value?: string | string[];\n\n /**\n * When `true`, the component manages its own selection state internally\n * using `React.useState`. The `value` prop is used only as the initial\n * value (i.e. `defaultValue`) and subsequent changes do not require an\n * external state update. `onChanged` is still fired so callers can\n * observe changes without owning the state.\n *\n * Has no effect when inside a pi/form (form context always takes\n * precedence).\n *\n * @default false\n */\n selfManaged?: boolean;\n\n /**\n * Visual style variant of the toggle buttons.\n * - `\"default\"` — transparent background, highlights on active.\n * - `\"outline\"` — bordered buttons, grouped or spaced.\n *\n * @default \"default\"\n */\n variant?: \"default\" | \"outline\";\n\n /**\n * Size of each toggle button.\n * @default \"default\"\n */\n size?: \"default\" | \"sm\" | \"lg\";\n\n /**\n * Gap between toggle buttons (in Tailwind spacing units).\n * `0` = buttons are joined (no gap, rounded ends only).\n * Positive values add space between each button.\n *\n * @default 0\n */\n spacing?: number;\n\n /** When true, the entire group is disabled and non-interactive. */\n disabled?: boolean;\n\n /** Extra Tailwind / CSS classes forwarded to the root element. */\n className?: string;\n};\n\nexport type PiToggleGroupChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /**\n * New selected value(s).\n * - In `\"single\"` mode: a `string` (empty string when nothing selected).\n * - In `\"multiple\"` mode: an array of `string`.\n */\n value: string | string[];\n};\n\nexport type PiToggleGroupEvents = {\n onChanged: PiToggleGroupChangedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAuB,mBAEvB,IAAc,EAGzB,CAAoB,GAET,IAAyB,EAAgB,GAAsB,CAC1E,SACF,CAAC,GAEY,IAAyB,EACpC,EAAuB,OACzB"}
1
+ {"version":3,"file":"toggleGroup.types.js","names":[],"sources":["../../../src/cards/toggleGroup/toggleGroup.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_TOGGLE_GROUP_CARD = \"pi/toggle-group\";\n\nexport const ToggleGroup = createCardDeclaration<\n PiToggleGroupProps,\n PiToggleGroupEvents\n>(PI_TOGGLE_GROUP_CARD);\n\nexport const PI_TOGGLE_GROUP_ACTION = registerActions(PI_TOGGLE_GROUP_CARD, [\n \"changed\",\n]);\n\nexport const onToggleGroupChanged = createOnAction<PiToggleGroupChangedEvent>(\n PI_TOGGLE_GROUP_ACTION.CHANGED,\n);\n\n/** @deprecated Use `onToggleGroupChanged` instead. */\nexport const onPiToggleGroupChanged = onToggleGroupChanged;\n\n// ---------------------------------------------------------------------------\n// Item type\n// ---------------------------------------------------------------------------\n\nexport type PiToggleGroupItem = {\n /** The value associated with this toggle item. */\n value: string;\n /** Human-readable label rendered inside the toggle button. */\n label: string;\n /** When true, this individual item is disabled. */\n disabled?: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiToggleGroupProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its selected value from form data and\n * writes back via form.handleChange.\n */\n name?: string;\n\n /**\n * The list of toggle items to display.\n */\n items: PiToggleGroupItem[];\n\n /**\n * Selection mode.\n * - `\"single\"` — at most one item can be active at a time.\n * - `\"multiple\"` — any number of items can be active simultaneously.\n *\n * @default \"single\"\n */\n type?: \"single\" | \"multiple\";\n\n /**\n * Controlled selected value(s).\n * - In `\"single\"` mode: a `string` (or `undefined` for nothing selected).\n * - In `\"multiple\"` mode: an array of `string`.\n *\n * Ignored when `name` is set and the component is inside a pi/form.\n * Also ignored when `selfManaged` is `true`.\n */\n value?: string | string[];\n\n /**\n * When `true`, the component manages its own selection state internally\n * using `React.useState`. The `value` prop is used only as the initial\n * value (i.e. `defaultValue`) and subsequent changes do not require an\n * external state update. `onChanged` is still fired so callers can\n * observe changes without owning the state.\n *\n * Has no effect when inside a pi/form (form context always takes\n * precedence).\n *\n * @default false\n */\n selfManaged?: boolean;\n\n /**\n * Visual style variant of the toggle buttons.\n * - `\"default\"` — transparent background, highlights on active.\n * - `\"outline\"` — bordered buttons, grouped or spaced.\n *\n * @default \"default\"\n */\n variant?: \"default\" | \"outline\";\n\n /**\n * Size of each toggle button.\n * @default \"default\"\n */\n size?: \"default\" | \"sm\" | \"lg\";\n\n /**\n * Gap between toggle buttons (in Tailwind spacing units).\n * `0` = buttons are joined (no gap, rounded ends only).\n * Positive values add space between each button.\n *\n * @default 0\n */\n spacing?: number;\n\n /** When true, the entire group is disabled and non-interactive. */\n disabled?: boolean;\n\n /** Extra Tailwind / CSS classes forwarded to the root element. */\n className?: string;\n};\n\nexport type PiToggleGroupChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /**\n * New selected value(s).\n * - In `\"single\"` mode: a `string` (empty string when nothing selected).\n * - In `\"multiple\"` mode: an array of `string`.\n */\n value: string | string[];\n};\n\nexport type PiToggleGroupEvents = {\n onChanged: PiToggleGroupChangedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAuB,mBAEvB,IAAc,EAGzB,CAAoB,GAET,IAAyB,EAAgB,GAAsB,CAC1E,SACF,CAAC,GAEY,IAAuB,EAClC,EAAuB,OACzB,GAGa,IAAyB"}
@@ -1,4 +1,5 @@
1
1
  import { createCardDeclaration as e } from "@pihanga2/core";
2
+ import "react";
2
3
  //#region src/cards/typography/typography.types.ts
3
4
  var t = "shad/typography", n = e(t);
4
5
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"typography.types.js","names":[],"sources":["../../../src/cards/typography/typography.types.ts"],"sourcesContent":["import * as React from \"react\";\nimport {PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\n\nexport const TYPOGRAPHY_CARD = \"shad/typography\";\n\nexport const Typography =\n createCardDeclaration<TypographyProps>(TYPOGRAPHY_CARD);\n\n/**\n * Semantic level controls both the rendered HTML element and default\n * Tailwind prose styling (following shadcn/ui typography conventions).\n */\nexport type TypographyLevel =\n | \"h1\"\n | \"h2\"\n | \"h3\"\n | \"h4\"\n | \"p\"\n | \"blockquote\"\n | \"code\"\n | \"lead\" // large muted intro paragraph\n | \"large\" // large text, semibold\n | \"small\" // small, medium-weight\n | \"muted\"; // small, muted-foreground\n\nexport type TypographyProps = {\n /** Plain text content. */\n text?: string;\n /** A child card rendered as content. */\n childCard?: PiCardRef;\n /** Inline paragraph: mix of literal strings and nested TypographyProps. */\n paragraph?: (string | TypographyProps)[];\n\n /** Semantic level — controls the HTML element and default prose styling. */\n level?: TypographyLevel;\n\n /** Additional CSS classes applied directly to the element. */\n className?: string;\n /** Inline styles applied directly to the element. */\n style?: React.CSSProperties;\n};\n"],"mappings":";;AAGA,IAAa,IAAkB,mBAElB,IACX,EAAuC,CAAe"}
1
+ {"version":3,"file":"typography.types.js","names":[],"sources":["../../../src/cards/typography/typography.types.ts"],"sourcesContent":["import * as React from \"react\";\nimport {type PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\n\nexport const TYPOGRAPHY_CARD = \"shad/typography\";\n\nexport const Typography =\n createCardDeclaration<TypographyProps>(TYPOGRAPHY_CARD);\n\n/**\n * Semantic level controls both the rendered HTML element and default\n * Tailwind prose styling (following shadcn/ui typography conventions).\n */\nexport type TypographyLevel =\n | \"h1\"\n | \"h2\"\n | \"h3\"\n | \"h4\"\n | \"p\"\n | \"blockquote\"\n | \"code\"\n | \"lead\" // large muted intro paragraph\n | \"large\" // large text, semibold\n | \"small\" // small, medium-weight\n | \"muted\"; // small, muted-foreground\n\nexport type TypographyProps = {\n /** Plain text content. */\n text?: string;\n /** A child card rendered as content. */\n childCard?: PiCardRef;\n /** Inline paragraph: mix of literal strings and nested TypographyProps. */\n paragraph?: (string | TypographyProps)[];\n\n /** Semantic level — controls the HTML element and default prose styling. */\n level?: TypographyLevel;\n\n /** Additional CSS classes applied directly to the element. */\n className?: string;\n /** Inline styles applied directly to the element. */\n style?: React.CSSProperties;\n};\n"],"mappings":";;;AAGA,IAAa,IAAkB,mBAElB,IACX,EAAuC,CAAe"}
@@ -0,0 +1,36 @@
1
+ import { cn as e } from "../lib/utils.js";
2
+ import * as t from "react";
3
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
4
+ import * as i from "@radix-ui/react-slider";
5
+ //#region src/components/ui/slider.tsx
6
+ function a({ className: a, defaultValue: o, value: s, min: c = 0, max: l = 100, ...u }) {
7
+ let d = t.useMemo(() => Array.isArray(s) ? s : Array.isArray(o) ? o : [c], [
8
+ s,
9
+ o,
10
+ c
11
+ ]);
12
+ return /* @__PURE__ */ r(i.Root, {
13
+ "data-slot": "slider",
14
+ defaultValue: o,
15
+ value: s,
16
+ min: c,
17
+ max: l,
18
+ className: e("relative flex w-full touch-none items-center select-none", "data-[disabled]:opacity-50", "data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44", "data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col", a),
19
+ ...u,
20
+ children: [/* @__PURE__ */ n(i.Track, {
21
+ "data-slot": "slider-track",
22
+ className: e("bg-muted relative grow overflow-hidden rounded-full", "data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full", "data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"),
23
+ children: /* @__PURE__ */ n(i.Range, {
24
+ "data-slot": "slider-range",
25
+ className: e("bg-primary absolute", "data-[orientation=horizontal]:h-full", "data-[orientation=vertical]:w-full")
26
+ })
27
+ }), Array.from({ length: d.length }, (t, r) => /* @__PURE__ */ n(i.Thumb, {
28
+ "data-slot": "slider-thumb",
29
+ className: e("border-primary bg-background ring-ring/50", "block size-4 shrink-0 rounded-full border-2 shadow-sm", "transition-[color,box-shadow]", "focus-visible:ring-[3px] focus-visible:outline-none", "disabled:pointer-events-none")
30
+ }, r))]
31
+ });
32
+ }
33
+ //#endregion
34
+ export { a as Slider };
35
+
36
+ //# sourceMappingURL=slider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slider.js","names":[],"sources":["../../../src/components/ui/slider.tsx"],"sourcesContent":["import * as React from \"react\";\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\n\nimport {cn} from \"@/components/lib/utils\";\n\nfunction Slider({\n className,\n defaultValue,\n value,\n min = 0,\n max = 100,\n ...props\n}: React.ComponentProps<typeof SliderPrimitive.Root>) {\n const _values = React.useMemo(\n () =>\n Array.isArray(value)\n ? value\n : Array.isArray(defaultValue)\n ? defaultValue\n : [min],\n [value, defaultValue, min],\n );\n\n return (\n <SliderPrimitive.Root\n data-slot=\"slider\"\n defaultValue={defaultValue}\n value={value}\n min={min}\n max={max}\n className={cn(\n \"relative flex w-full touch-none items-center select-none\",\n \"data-[disabled]:opacity-50\",\n \"data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44\",\n \"data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col\",\n className,\n )}\n {...props}\n >\n <SliderPrimitive.Track\n data-slot=\"slider-track\"\n className={cn(\n \"bg-muted relative grow overflow-hidden rounded-full\",\n \"data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full\",\n \"data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5\",\n )}\n >\n <SliderPrimitive.Range\n data-slot=\"slider-range\"\n className={cn(\n \"bg-primary absolute\",\n \"data-[orientation=horizontal]:h-full\",\n \"data-[orientation=vertical]:w-full\",\n )}\n />\n </SliderPrimitive.Track>\n {Array.from({length: _values.length}, (_, i) => (\n <SliderPrimitive.Thumb\n key={i}\n data-slot=\"slider-thumb\"\n className={cn(\n \"border-primary bg-background ring-ring/50\",\n \"block size-4 shrink-0 rounded-full border-2 shadow-sm\",\n \"transition-[color,box-shadow]\",\n \"focus-visible:ring-[3px] focus-visible:outline-none\",\n \"disabled:pointer-events-none\",\n )}\n />\n ))}\n </SliderPrimitive.Root>\n );\n}\n\nexport {Slider};\n"],"mappings":";;;;;AAKA,SAAS,EAAO,EACd,cACA,iBACA,UACA,SAAM,GACN,SAAM,KACN,GAAG,KACiD;CACpD,IAAM,IAAU,EAAM,cAElB,MAAM,QAAQ,CAAK,IACf,IACA,MAAM,QAAQ,CAAY,IACxB,IACA,CAAC,CAAG,GACZ;EAAC;EAAO;EAAc;CAAG,CAC3B;CAEA,OACE,kBAAC,EAAgB,MAAjB;EACE,aAAU;EACI;EACP;EACF;EACA;EACL,WAAW,EACT,4DACA,8BACA,2EACA,2EACA,CACF;EACA,GAAI;YAbN,CAeE,kBAAC,EAAgB,OAAjB;GACE,aAAU;GACV,WAAW,EACT,uDACA,4EACA,sEACF;aAEA,kBAAC,EAAgB,OAAjB;IACE,aAAU;IACV,WAAW,EACT,uBACA,wCACA,oCACF;GACD,CAAA;EACoB,CAAA,GACtB,MAAM,KAAK,EAAC,QAAQ,EAAQ,OAAM,IAAI,GAAG,MACxC,kBAAC,EAAgB,OAAjB;GAEE,aAAU;GACV,WAAW,EACT,6CACA,yDACA,iCACA,uDACA,8BACF;EACD,GATM,CASN,CACF,CACmB;;AAE1B"}
@@ -2,6 +2,7 @@
2
2
  import { cn as e } from "../../lib/utils.js";
3
3
  import { toggleVariants as t } from "./toggle.js";
4
4
  import * as n from "react";
5
+ import "class-variance-authority";
5
6
  import { jsx as r } from "react/jsx-runtime";
6
7
  import { ToggleGroup as i } from "radix-ui";
7
8
  //#region src/components/ui/toggle-group.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-group.js","names":[],"sources":["../../../src/components/ui/toggle-group.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { type VariantProps } from \"class-variance-authority\"\nimport { ToggleGroup as ToggleGroupPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\nimport { toggleVariants } from \"@/components/ui/toggle\"\n\nconst ToggleGroupContext = React.createContext<\n VariantProps<typeof toggleVariants> & {\n spacing?: number\n }\n>({\n size: \"default\",\n variant: \"default\",\n spacing: 0,\n})\n\nfunction ToggleGroup({\n className,\n variant,\n size,\n spacing = 0,\n children,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &\n VariantProps<typeof toggleVariants> & {\n spacing?: number\n }) {\n return (\n <ToggleGroupPrimitive.Root\n data-slot=\"toggle-group\"\n data-variant={variant}\n data-size={size}\n data-spacing={spacing}\n style={{ \"--gap\": spacing } as React.CSSProperties}\n className={cn(\n \"group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs\",\n className\n )}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size, spacing }}>\n {children}\n </ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n )\n}\n\nfunction ToggleGroupItem({\n className,\n children,\n variant,\n size,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &\n VariantProps<typeof toggleVariants>) {\n const context = React.useContext(ToggleGroupContext)\n\n return (\n <ToggleGroupPrimitive.Item\n data-slot=\"toggle-group-item\"\n data-variant={context.variant || variant}\n data-size={context.size || size}\n data-spacing={context.spacing}\n className={cn(\n toggleVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n \"w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10\",\n \"data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l\",\n className\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n )\n}\n\nexport { ToggleGroup, ToggleGroupItem }\n"],"mappings":";;;;;;;AASA,IAAM,IAAqB,EAAM,cAI/B;CACA,MAAM;CACN,SAAS;CACT,SAAS;AACX,CAAC;AAED,SAAS,EAAY,EACnB,cACA,YACA,SACA,aAAU,GACV,aACA,GAAG,KAIA;CACH,OACE,kBAAC,EAAqB,MAAtB;EACE,aAAU;EACV,gBAAc;EACd,aAAW;EACX,gBAAc;EACd,OAAO,EAAE,SAAS,EAAQ;EAC1B,WAAW,EACT,6IACA,CACF;EACA,GAAI;YAEJ,kBAAC,EAAmB,UAApB;GAA6B,OAAO;IAAE;IAAS;IAAM;GAAQ;GAC1D;EAC0B,CAAA;CACJ,CAAA;AAE/B;AAEA,SAAS,EAAgB,EACvB,cACA,aACA,YACA,SACA,GAAG,KAEkC;CACrC,IAAM,IAAU,EAAM,WAAW,CAAkB;CAEnD,OACE,kBAAC,EAAqB,MAAtB;EACE,aAAU;EACV,gBAAc,EAAQ,WAAW;EACjC,aAAW,EAAQ,QAAQ;EAC3B,gBAAc,EAAQ;EACtB,WAAW,EACT,EAAe;GACb,SAAS,EAAQ,WAAW;GAC5B,MAAM,EAAQ,QAAQ;EACxB,CAAC,GACD,8DACA,+OACA,CACF;EACA,GAAI;EAEH;CACwB,CAAA;AAE/B"}
1
+ {"version":3,"file":"toggle-group.js","names":[],"sources":["../../../src/components/ui/toggle-group.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { type VariantProps } from \"class-variance-authority\"\nimport { ToggleGroup as ToggleGroupPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\nimport { toggleVariants } from \"@/components/ui/toggle\"\n\nconst ToggleGroupContext = React.createContext<\n VariantProps<typeof toggleVariants> & {\n spacing?: number\n }\n>({\n size: \"default\",\n variant: \"default\",\n spacing: 0,\n})\n\nfunction ToggleGroup({\n className,\n variant,\n size,\n spacing = 0,\n children,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &\n VariantProps<typeof toggleVariants> & {\n spacing?: number\n }) {\n return (\n <ToggleGroupPrimitive.Root\n data-slot=\"toggle-group\"\n data-variant={variant}\n data-size={size}\n data-spacing={spacing}\n style={{ \"--gap\": spacing } as React.CSSProperties}\n className={cn(\n \"group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs\",\n className\n )}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size, spacing }}>\n {children}\n </ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n )\n}\n\nfunction ToggleGroupItem({\n className,\n children,\n variant,\n size,\n ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &\n VariantProps<typeof toggleVariants>) {\n const context = React.useContext(ToggleGroupContext)\n\n return (\n <ToggleGroupPrimitive.Item\n data-slot=\"toggle-group-item\"\n data-variant={context.variant || variant}\n data-size={context.size || size}\n data-spacing={context.spacing}\n className={cn(\n toggleVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n \"w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10\",\n \"data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l\",\n className\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n )\n}\n\nexport { ToggleGroup, ToggleGroupItem }\n"],"mappings":";;;;;;;;AASA,IAAM,IAAqB,EAAM,cAI/B;CACA,MAAM;CACN,SAAS;CACT,SAAS;AACX,CAAC;AAED,SAAS,EAAY,EACnB,cACA,YACA,SACA,aAAU,GACV,aACA,GAAG,KAIA;CACH,OACE,kBAAC,EAAqB,MAAtB;EACE,aAAU;EACV,gBAAc;EACd,aAAW;EACX,gBAAc;EACd,OAAO,EAAE,SAAS,EAAQ;EAC1B,WAAW,EACT,6IACA,CACF;EACA,GAAI;YAEJ,kBAAC,EAAmB,UAApB;GAA6B,OAAO;IAAE;IAAS;IAAM;GAAQ;GAC1D;EAC0B,CAAA;CACJ,CAAA;AAE/B;AAEA,SAAS,EAAgB,EACvB,cACA,aACA,YACA,SACA,GAAG,KAEkC;CACrC,IAAM,IAAU,EAAM,WAAW,CAAkB;CAEnD,OACE,kBAAC,EAAqB,MAAtB;EACE,aAAU;EACV,gBAAc,EAAQ,WAAW;EACjC,aAAW,EAAQ,QAAQ;EAC3B,gBAAc,EAAQ;EACtB,WAAW,EACT,EAAe;GACb,SAAS,EAAQ,WAAW;GAC5B,MAAM,EAAQ,QAAQ;EACxB,CAAC,GACD,8DACA,+OACA,CACF;EACA,GAAI;EAEH;CACwB,CAAA;AAE/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pihanga2/shadcn",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Pihanga core card components built on shadcn/ui and Radix UI — the npm distribution of pihanga-shadcn.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,6 +44,10 @@
44
44
  "import": "./cards/field/index.js",
45
45
  "types": "./cards/field/index.d.ts"
46
46
  },
47
+ "./cards/fileDrop": {
48
+ "import": "./cards/fileDrop/index.js",
49
+ "types": "./cards/fileDrop/index.d.ts"
50
+ },
47
51
  "./cards/flexGrid": {
48
52
  "import": "./cards/flexGrid/index.js",
49
53
  "types": "./cards/flexGrid/index.d.ts"
@@ -96,6 +100,14 @@
96
100
  "import": "./cards/select/index.js",
97
101
  "types": "./cards/select/index.d.ts"
98
102
  },
103
+ "./cards/slider": {
104
+ "import": "./cards/slider/index.js",
105
+ "types": "./cards/slider/index.d.ts"
106
+ },
107
+ "./cards/sliderValue": {
108
+ "import": "./cards/sliderValue/index.js",
109
+ "types": "./cards/sliderValue/index.d.ts"
110
+ },
99
111
  "./cards/stack": {
100
112
  "import": "./cards/stack/index.js",
101
113
  "types": "./cards/stack/index.d.ts"
@@ -149,6 +161,7 @@
149
161
  "./cards/dialog/index.js",
150
162
  "./cards/dropDownMenu/index.js",
151
163
  "./cards/field/index.js",
164
+ "./cards/fileDrop/index.js",
152
165
  "./cards/flexGrid/index.js",
153
166
  "./cards/form/index.js",
154
167
  "./cards/framework/index.js",
@@ -162,6 +175,8 @@
162
175
  "./cards/pageWithNavbar/index.js",
163
176
  "./cards/pasteTarget/index.js",
164
177
  "./cards/select/index.js",
178
+ "./cards/slider/index.js",
179
+ "./cards/sliderValue/index.js",
165
180
  "./cards/stack/index.js",
166
181
  "./cards/stepper/index.js",
167
182
  "./cards/switch/index.js",
@@ -190,13 +205,14 @@
190
205
  "react": "^19.1.0",
191
206
  "react-dom": "^19.1.0",
192
207
  "@pihanga2/core": "*",
193
- "@pihanga2/cards": "^0.3.15"
208
+ "@pihanga2/cards": "*"
194
209
  },
195
210
  "dependencies": {
196
211
  "@radix-ui/react-dialog": "^1.1.15",
197
212
  "@radix-ui/react-dropdown-menu": "^2.1.16",
198
213
  "@radix-ui/react-menubar": "^1.1.16",
199
214
  "@radix-ui/react-select": "^2.2.6",
215
+ "@radix-ui/react-slider": "^1.2.3",
200
216
  "@radix-ui/react-slot": "^1.2.4",
201
217
  "@radix-ui/react-switch": "^1.1.2",
202
218
  "@radix-ui/react-tabs": "^1.1.13",
@@ -205,6 +221,7 @@
205
221
  "clsx": "^2.1.1",
206
222
  "lucide-react": "^0.513.0",
207
223
  "radix-ui": "^1.4.3",
224
+ "react-drag-drop-files": "^3.0.1",
208
225
  "sonner": "^2.0.7",
209
226
  "tailwind-merge": "^3.3.0"
210
227
  }
@@ -1,2 +1,2 @@
1
- .overlay-wrapper{flex-direction:column;width:100%;min-width:0;display:flex;position:relative}.overlay-wrapper.is-loading.fill-parent{min-height:12rem}.overlay-content{flex-direction:column;flex-grow:1;width:100%;min-width:0;display:flex;position:relative;overflow-y:hidden}.overlay-wrapper.fill-parent .overlay-content{min-height:inherit}.loading-overlay{opacity:0;pointer-events:none;z-index:2;background:oklch(100% 0 0/.7);justify-content:center;align-items:center;transition:opacity .15s;display:flex;position:absolute;inset:0}.overlay-wrapper.viewport-centered .loading-overlay{z-index:50;position:fixed;inset:0}.dark .loading-overlay{background:oklch(14.5% 0 0/.5)}.overlay-wrapper.is-loading .loading-overlay{opacity:1;pointer-events:auto}.loading-overlay__content{color:var(--muted-foreground);align-items:center;gap:.5rem;font-size:.875rem;display:flex}.window{justify-content:center;width:100%;display:flex}.page{grid-template:"header"4rem"main"1fr"footer"/100%;width:100%;height:100vh;min-height:100vh;display:grid}.header{border-bottom:1px solid var(--border);background-color:var(--background);grid-area:header;align-items:center;gap:1rem;padding-left:1rem;padding-right:1rem;display:flex}@media (width>=768px){.header{padding-left:1.5rem;padding-right:1.5rem}}.title-section{align-items:center;gap:.5rem;display:inline-flex}.title-section .title-icon{flex-shrink:0;width:1.5rem;height:1.5rem}.title-section .title-text{color:var(--foreground);font-size:1.125rem;font-weight:600;line-height:1.75rem}.nav-md{display:none}@media (width>=768px){.nav-md{flex-direction:row;align-items:center;gap:1.25rem;display:flex}}@media (width>=1024px){.nav-md{gap:1.5rem}}.nav-md .nav-link{color:var(--muted-foreground);padding-left:0;padding-right:0;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.nav-md .nav-link:hover{color:var(--foreground)}.nav-sm{gap:1.5rem;padding:1rem;font-size:1.125rem;font-weight:500;line-height:1.75rem;display:grid}.nav-sm .nav-link{color:var(--muted-foreground);justify-content:flex-start;padding-left:0;padding-right:0;font-size:1.125rem;line-height:1.75rem}.nav-sm .nav-link:hover{color:var(--foreground)}.header-actions{align-items:center;gap:.5rem;margin-left:auto;display:flex}@media (width>=1024px){.header-actions{gap:1rem}}.main{background-color:var(--background);grid-area:main;min-height:0;padding:.5rem 1rem;overflow-y:auto}@media (width>=768px){.main{padding:1rem 2rem}}.footer{background-color:var(--background);color:var(--muted-foreground);grid-area:footer;padding:.5rem 1rem}@media (width>=768px){.footer{padding:1rem 2rem}}.pihanga-paste-target{border:2px dashed #999}.pihanga-paste-target .paste-target-msg-title{font-size:1.2em}.pihanga-paste-target textarea:focus{outline:none}.pihanga-paste-target-focused{border-width:3px;border-color:#007bff}.pihanga-paste-target-focused .paste-target-focus-reminder{display:none}.pi-stepper{--pi-stepper-indicator-size-sm:1.5rem;--pi-stepper-indicator-size-md:2rem;--pi-stepper-indicator-size-lg:2.5rem;--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-md);--pi-stepper-connector-thickness:2px;--pi-stepper-connector-min-height:1.5rem;--pi-stepper-label-max-width:6rem}.pi-stepper--sm{--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-sm)}.pi-stepper--md{--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-md)}.pi-stepper--lg{--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-lg)}.pi-stepper__indicator{transition:background-color .2s,border-color .2s,color .2s,outline-color .2s}.pi-stepper__indicator--clickable{cursor:pointer}.pi-stepper__indicator--clickable:hover{opacity:.8}.pi-stepper__indicator--static{cursor:default}.pi-stepper__connector{transition:background-color .3s}.pi-stepper__connector--vertical{min-height:var(--pi-stepper-connector-min-height)}.pi-stepper__label-title{transition:color .2s}
1
+ .pi-file-drop-root label{border:2px dashed #999;flex-grow:1;justify-content:space-between;max-width:100%;display:flex}.pi-file-drop-root .dropzone-msg{cursor:pointer;text-align:center;flex-grow:4;margin:3em 0}.pi-file-drop-root .pi-progress{max-width:100%;padding:1.25em}.pi-file-drop-root .pi-progress-label{font-size:1rem;font-weight:600;line-height:1.5rem}.pi-file-drop -root.pi-progress-container{background-color:#dadfe5;border-radius:4px;height:1rem;display:flex;position:relative;overflow:hidden}.pi-file-drop-root .pi-progress-bar{color:#fff;background-color:#0054a6;flex-direction:column;justify-content:center;display:flex;overflow:hidden}.pi-file-drop-root .pi-progress .label{font-size:1em;display:block}.overlay-wrapper{flex-direction:column;width:100%;min-width:0;display:flex;position:relative}.overlay-wrapper.is-loading.fill-parent{min-height:12rem}.overlay-content{flex-direction:column;flex-grow:1;width:100%;min-width:0;display:flex;position:relative;overflow-y:hidden}.overlay-wrapper.fill-parent .overlay-content{min-height:inherit}.loading-overlay{opacity:0;pointer-events:none;z-index:2;background:oklch(100% 0 0/.7);justify-content:center;align-items:center;transition:opacity .15s;display:flex;position:absolute;inset:0}.overlay-wrapper.viewport-centered .loading-overlay{z-index:50;position:fixed;inset:0}.dark .loading-overlay{background:oklch(14.5% 0 0/.5)}.overlay-wrapper.is-loading .loading-overlay{opacity:1;pointer-events:auto}.loading-overlay__content{color:var(--muted-foreground);align-items:center;gap:.5rem;font-size:.875rem;display:flex}.window{justify-content:center;width:100%;height:100%;display:flex}.page{flex-direction:column;flex:1;width:100%;height:100%;display:flex}.header{border-bottom:1px solid var(--border);background-color:var(--background);flex-shrink:0;align-items:center;gap:1rem;padding-left:1rem;padding-right:1rem;display:flex}@media (width>=768px){.header{padding-left:1.5rem;padding-right:1.5rem}}.title-section{align-items:center;gap:.5rem;display:inline-flex}.title-section .title-icon{flex-shrink:0;width:1.5rem;height:1.5rem}.title-section .title-text{color:var(--foreground);font-size:1.125rem;font-weight:600;line-height:1.75rem}.nav-md{display:none}@media (width>=768px){.nav-md{flex-direction:row;align-items:center;gap:1.25rem;display:flex}}@media (width>=1024px){.nav-md{gap:1.5rem}}.nav-md .nav-link{color:var(--muted-foreground);padding-left:0;padding-right:0;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.nav-md .nav-link:hover{color:var(--foreground)}.nav-sm{gap:1.5rem;padding:1rem;font-size:1.125rem;font-weight:500;line-height:1.75rem;display:grid}.nav-sm .nav-link{color:var(--muted-foreground);justify-content:flex-start;padding-left:0;padding-right:0;font-size:1.125rem;line-height:1.75rem}.nav-sm .nav-link:hover{color:var(--foreground)}.header-actions{align-items:center;gap:.5rem;margin-left:auto;display:flex}@media (width>=1024px){.header-actions{gap:1rem}}.main{background-color:var(--background);flex:1;min-height:0;padding:.5rem 1rem;overflow-y:auto}@media (width>=768px){.main{padding:1rem 2rem}}.footer{background-color:var(--background);color:var(--muted-foreground);flex-shrink:0;padding:.5rem 1rem}@media (width>=768px){.footer{padding:1rem 2rem}}.pihanga-paste-target{border:2px dashed #999}.pihanga-paste-target .paste-target-msg-title{font-size:1.2em}.pihanga-paste-target textarea:focus{outline:none}.pihanga-paste-target-focused{border-width:3px;border-color:#007bff}.pihanga-paste-target-focused .paste-target-focus-reminder{display:none}.pi-stepper{--pi-stepper-indicator-size-sm:1.5rem;--pi-stepper-indicator-size-md:2rem;--pi-stepper-indicator-size-lg:2.5rem;--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-md);--pi-stepper-connector-thickness:2px;--pi-stepper-connector-min-height:1.5rem;--pi-stepper-label-max-width:6rem}.pi-stepper--sm{--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-sm)}.pi-stepper--md{--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-md)}.pi-stepper--lg{--pi-stepper-indicator-size:var(--pi-stepper-indicator-size-lg)}.pi-stepper__indicator{transition:background-color .2s,border-color .2s,color .2s,outline-color .2s}.pi-stepper__indicator--clickable{cursor:pointer}.pi-stepper__indicator--clickable:hover{opacity:.8}.pi-stepper__indicator--static{cursor:default}.pi-stepper__connector{transition:background-color .3s}.pi-stepper__connector--vertical{min-height:var(--pi-stepper-connector-min-height)}.pi-stepper__label-title{transition:color .2s}
2
2
  /*$vite$:1*/
@@ -1,102 +0,0 @@
1
- import { ChartConfig } from '../../components/ui/chart';
2
- export declare const PI_CHART_GRAPH_CARD = "shad/chart-graph";
3
- export declare const ChartGraph: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<PiChartGraphProps, S, {}>) => import('@pihanga2/core').PiCardDef;
4
- export type { ChartConfig };
5
- export type PiChartSeries = {
6
- /** Key in each data-point object whose value will be plotted on the y-axis. */
7
- dataKey: string;
8
- /** Human-readable label used in the tooltip and legend. Defaults to `dataKey`. */
9
- label?: string;
10
- /**
11
- * CSS colour string for this series.
12
- * Falls back to the shadcn chart CSS variables
13
- * (`hsl(var(--chart-1))`, `hsl(var(--chart-2))`, …) in order.
14
- */
15
- color?: string;
16
- };
17
- export type PiChartGraphProps = {
18
- /**
19
- * Whether to render an **area** chart (filled) or a **line** chart (stroke only).
20
- */
21
- chartType: "area" | "line";
22
- /**
23
- * Array of data points. Each entry must contain:
24
- * - a value for `xDataKey` (used for the x-axis labels), and
25
- * - a numeric value for each `series[].dataKey`.
26
- *
27
- * @example
28
- * ```ts
29
- * [
30
- * { month: "Jan", desktop: 186, mobile: 80 },
31
- * { month: "Feb", desktop: 305, mobile: 200 },
32
- * ]
33
- * ```
34
- */
35
- data: Array<Record<string, unknown>>;
36
- /**
37
- * Series definitions. Each entry describes one plotted line or area.
38
- * At least one series is required.
39
- */
40
- series: PiChartSeries[];
41
- /** Key inside each data-point object used for the x-axis tick labels. */
42
- xDataKey: string;
43
- /**
44
- * Optional card title rendered above the chart.
45
- * When either `title` or `description` is set the chart is wrapped in a
46
- * shadcn `<Card>` shell; otherwise it renders as a bare `<div>`.
47
- */
48
- title?: string;
49
- /**
50
- * Optional subtitle rendered below `title`.
51
- * Has no effect when `title` is not set.
52
- */
53
- description?: string;
54
- /**
55
- * Minimum chart height in pixels.
56
- * The chart expands if the responsive container requires more space.
57
- * Defaults to `250`.
58
- */
59
- height?: number;
60
- /** Show a legend beneath the chart. Defaults to `true`. */
61
- showLegend?: boolean;
62
- /** Show horizontal cartesian grid lines. Defaults to `true`. */
63
- showGrid?: boolean;
64
- /**
65
- * Show the y-axis with numeric tick labels on the left edge of the chart.
66
- * Defaults to `false` (y-axis hidden) to keep the chart compact.
67
- */
68
- showYAxis?: boolean;
69
- /**
70
- * Unit string appended to every y-axis tick label (e.g. `"ms"`, `"%"`, `" km"`).
71
- * Only visible when `showYAxis` is `true`.
72
- *
73
- * @example `yAxisUnit="%"` renders ticks as `"0%"`, `"50%"`, `"100%"`.
74
- */
75
- yAxisUnit?: string;
76
- /**
77
- * Unit string appended to every x-axis tick label.
78
- * Useful when x-axis values are numeric (e.g. seconds, iterations).
79
- * Has no effect when x-axis values are already formatted strings (e.g. month names).
80
- *
81
- * @example `xAxisUnit="s"` renders ticks as `"1s"`, `"2s"`, etc.
82
- */
83
- xAxisUnit?: string;
84
- /**
85
- * Stack all area series on top of each other (area chart only).
86
- * When `false` (default) the filled areas overlap.
87
- */
88
- stacked?: boolean;
89
- /**
90
- * Opacity of the filled area (area chart only).
91
- * Range 0–1. Defaults to `0.4`.
92
- */
93
- fillOpacity?: number;
94
- /**
95
- * Suppress the recharts entry animation so the chart renders immediately
96
- * without the "draw-in" / "unfold" effect.
97
- * Defaults to `false` (animation enabled).
98
- */
99
- suppressAnimation?: boolean;
100
- /** Extra Tailwind / CSS classes forwarded to the outermost element. */
101
- className?: string;
102
- };
@@ -1 +0,0 @@
1
- export * from './chartGraph.types';