@pihanga2/shadcn 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/AGENT.building-cards.md +413 -0
  2. package/AGENT.md +50 -0
  3. package/AGENT.using-cards.md +1242 -0
  4. package/cards/box/box.types.d.ts +1 -4
  5. package/cards/box/box.types.js.map +1 -1
  6. package/cards/core-index.js +6 -6
  7. package/cards/fileDrop/fileDrop.component.d.ts +5 -0
  8. package/cards/fileDrop/fileDrop.types.d.ts +43 -0
  9. package/cards/fileDrop/index.d.ts +2 -0
  10. package/cards/icons.js +7 -3
  11. package/cards/icons.js.map +1 -1
  12. package/cards/index.d.ts +1 -0
  13. package/cards/stack/stack.types.d.ts +19 -22
  14. package/cards/stack/stack.types.js +1 -1
  15. package/cards/stack/stack.types.js.map +1 -1
  16. package/cards/tabs/index.js +4 -4
  17. package/cards/tabs/tabs.types.d.ts +2 -0
  18. package/cards/tabs/tabs.types.js +2 -2
  19. package/cards/tabs/tabs.types.js.map +1 -1
  20. package/cards/types.d.ts +4 -0
  21. package/cards/types.js.map +1 -1
  22. package/package.json +9 -1
  23. package/pihanga-shadcn.css +1 -1
  24. package/mountain-snow.svg +0 -4
  25. package/r/badge.json +0 -35
  26. package/r/box.json +0 -26
  27. package/r/button.json +0 -39
  28. package/r/checkbox.json +0 -31
  29. package/r/conditional.json +0 -30
  30. package/r/dataTable.json +0 -43
  31. package/r/dialog.json +0 -36
  32. package/r/dropDownMenu.json +0 -47
  33. package/r/field.json +0 -35
  34. package/r/flexGrid.json +0 -32
  35. package/r/form.json +0 -37
  36. package/r/framework.json +0 -28
  37. package/r/graphin.json +0 -42
  38. package/r/input.json +0 -35
  39. package/r/jsonViewer.json +0 -40
  40. package/r/list.json +0 -39
  41. package/r/loadingOverlay.json +0 -39
  42. package/r/loadingSkeleton.json +0 -30
  43. package/r/markdownViewer.json +0 -51
  44. package/r/menu.json +0 -34
  45. package/r/modeToggle.json +0 -36
  46. package/r/navbarSearch.json +0 -31
  47. package/r/pageWithNavbar.json +0 -46
  48. package/r/pasteTarget.json +0 -41
  49. package/r/pihanga-base.json +0 -11
  50. package/r/pihanga-cards-icons.json +0 -16
  51. package/r/pihanga-cards-types.json +0 -16
  52. package/r/pihanga-hook-use-is-touch-device.json +0 -15
  53. package/r/pihanga-lib-utils.json +0 -18
  54. package/r/pihanga-theme-provider.json +0 -25
  55. package/r/pihanga-ui-extras.json +0 -68
  56. package/r/registry.json +0 -171
  57. package/r/resizable.json +0 -35
  58. package/r/select.json +0 -35
  59. package/r/stack.json +0 -27
  60. package/r/stepper.json +0 -39
  61. package/r/switch.json +0 -36
  62. package/r/tabs.json +0 -33
  63. package/r/textField.json +0 -32
  64. package/r/toast.json +0 -32
  65. package/r/toggleGroup.json +0 -35
  66. package/r/typography.json +0 -31
@@ -1,9 +1,6 @@
1
1
  import { PiCardRef } from '@pihanga2/core';
2
+ import { AlignItemsT } from '../types';
2
3
  export declare const BOX_CARD = "shad/box";
3
- /**
4
- * CSS `align-items` values supported by the Box card.
5
- */
6
- export type AlignItemsT = "normal" | "stretch" | "center" | "flex-start" | "flex-end" | "start" | "end" | "baseline" | "initial" | "inherit";
7
4
  /**
8
5
  * Responsive display grid breakpoints.
9
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"box.types.js","names":[],"sources":["../../../src/cards/box/box.types.ts"],"sourcesContent":["import {type PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\n\nexport const BOX_CARD = \"shad/box\";\n\n/**\n * CSS `align-items` values supported by the Box card.\n */\nexport type AlignItemsT =\n | \"normal\"\n | \"stretch\"\n | \"center\"\n | \"flex-start\"\n | \"flex-end\"\n | \"start\"\n | \"end\"\n | \"baseline\"\n | \"initial\"\n | \"inherit\";\n\n/**\n * Responsive display grid breakpoints.\n *\n * Each key maps to a CSS display value applied at that viewport width:\n * - `xs`: < 640 px (default / mobile-first)\n * - `sm`: ≥ 640 px\n * - `md`: ≥ 768 px\n * - `lg`: ≥ 1024 px\n * - `xl`: ≥ 1280 px\n * - `xxl`: ≥ 1536 px\n */\nexport type DisplayGridT = {\n xs?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n xxl?: string;\n};\n\nexport type BoxProps<S = object> = {\n /** Child card refs rendered inside the box */\n content?: PiCardRef[];\n\n /** Override the root element type */\n component?: React.ElementType;\n\n /** Fixed height in pixels */\n height?: number;\n /** Fixed width in pixels */\n width?: number;\n\n marginTop?: number;\n marginBottom?: number;\n marginLeft?: number;\n marginRight?: number;\n\n paddingTop?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n paddingRight?: number;\n\n alignItems?: AlignItemsT;\n /** Tailwind gap spacing units */\n gap?: number;\n /** Uniform padding in pixels */\n padding?: number;\n /** Responsive display grid breakpoints */\n display?: DisplayGridT;\n\n /** Card style object (use the `shad` key for Tailwind-compatible overrides) */\n style?: S;\n /** Additional Tailwind utility classes */\n className?: string;\n};\n\n/**\n * Factory function for declaring a `shad/box` card instance.\n *\n * ```ts\n * import {registerCard} from \"@pihanga2/core\";\n * import {Box} from \"@/cards/box\";\n *\n * registerCard(\"myApp/spacer\", Box({height: 24}));\n *\n * registerCard(\"myApp/contentRegion\", Box({\n * content: [\"myApp/card1\", \"myApp/card2\"],\n * paddingTop: 16,\n * className: \"rounded-lg border bg-card\",\n * }));\n * ```\n */\nexport const Box = createCardDeclaration<BoxProps>(BOX_CARD);\n"],"mappings":";;AAEA,IAAa,IAAW,YAyFX,IAAM,EAAgC,CAAQ"}
1
+ {"version":3,"file":"box.types.js","names":[],"sources":["../../../src/cards/box/box.types.ts"],"sourcesContent":["import {type PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\nimport { AlignItemsT } from \"../types\";\n\nexport const BOX_CARD = \"shad/box\";\n\n/**\n * Responsive display grid breakpoints.\n *\n * Each key maps to a CSS display value applied at that viewport width:\n * - `xs`: < 640 px (default / mobile-first)\n * - `sm`: ≥ 640 px\n * - `md`: ≥ 768 px\n * - `lg`: ≥ 1024 px\n * - `xl`: ≥ 1280 px\n * - `xxl`: ≥ 1536 px\n */\nexport type DisplayGridT = {\n xs?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n xxl?: string;\n};\n\nexport type BoxProps<S = object> = {\n /** Child card refs rendered inside the box */\n content?: PiCardRef[];\n\n /** Override the root element type */\n component?: React.ElementType;\n\n /** Fixed height in pixels */\n height?: number;\n /** Fixed width in pixels */\n width?: number;\n\n marginTop?: number;\n marginBottom?: number;\n marginLeft?: number;\n marginRight?: number;\n\n paddingTop?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n paddingRight?: number;\n\n alignItems?: AlignItemsT;\n /** Tailwind gap spacing units */\n gap?: number;\n /** Uniform padding in pixels */\n padding?: number;\n /** Responsive display grid breakpoints */\n display?: DisplayGridT;\n\n /** Card style object (use the `shad` key for Tailwind-compatible overrides) */\n style?: S;\n /** Additional Tailwind utility classes */\n className?: string;\n};\n\n/**\n * Factory function for declaring a `shad/box` card instance.\n *\n * ```ts\n * import {registerCard} from \"@pihanga2/core\";\n * import {Box} from \"@/cards/box\";\n *\n * registerCard(\"myApp/spacer\", Box({height: 24}));\n *\n * registerCard(\"myApp/contentRegion\", Box({\n * content: [\"myApp/card1\", \"myApp/card2\"],\n * paddingTop: 16,\n * className: \"rounded-lg border bg-card\",\n * }));\n * ```\n */\nexport const Box = createCardDeclaration<BoxProps>(BOX_CARD);\n"],"mappings":";;AAGA,IAAa,IAAW,YA0EX,IAAM,EAAgC,CAAQ"}
@@ -48,14 +48,14 @@ import { STEPPER_ACTION as Ue, STEPPER_CARD as We, Stepper as Ge, onStepperStepC
48
48
  import "./stepper/index.js";
49
49
  import { PI_SWITCH_ACTION as qe, PI_SWITCH_CARD as Je, Switch as Ye, onPiSwitchChanged as Xe } from "./switch/switch.types.js";
50
50
  import "./switch/index.js";
51
- import { SdTabs as Ze, TABS_ACTION as Qe, TABS_CARD as $e, onTabsTabChanged as et } from "./tabs/tabs.types.js";
51
+ import { SdTabs as Ze, TABS_ACTION as Qe, TABS_CARD as $e, Tabs as et, onTabsTabChanged as tt } from "./tabs/tabs.types.js";
52
52
  import "./tabs/index.js";
53
- import { PI_TEXT_FIELD_ACTION as tt, PI_TEXT_FIELD_CARD as nt, TextField as rt, onPiTextFieldChanged as it } from "./textField/textField.types.js";
53
+ import { PI_TEXT_FIELD_ACTION as nt, PI_TEXT_FIELD_CARD as rt, TextField as it, onPiTextFieldChanged as at } from "./textField/textField.types.js";
54
54
  import "./textField/index.js";
55
- import { PI_TOAST_ACTION as at, PI_TOAST_CARD as ot, TOAST_OP_ACTION as st, Toast as ct, dispatchShowToast as lt, onPiToastClosed as ut, onShowToast as dt } from "./toast/toast.types.js";
55
+ import { PI_TOAST_ACTION as ot, PI_TOAST_CARD as st, TOAST_OP_ACTION as ct, Toast as lt, dispatchShowToast as ut, onPiToastClosed as dt, onShowToast as ft } from "./toast/toast.types.js";
56
56
  import "./toast/index.js";
57
- import { PI_TOGGLE_GROUP_ACTION as ft, PI_TOGGLE_GROUP_CARD as pt, ToggleGroup as mt, onPiToggleGroupChanged as ht } from "./toggleGroup/toggleGroup.types.js";
57
+ import { PI_TOGGLE_GROUP_ACTION as pt, PI_TOGGLE_GROUP_CARD as mt, ToggleGroup as ht, onPiToggleGroupChanged as gt } from "./toggleGroup/toggleGroup.types.js";
58
58
  import "./toggleGroup/index.js";
59
- import { TYPOGRAPHY_CARD as gt, Typography as _t } from "./typography/typography.types.js";
59
+ import { TYPOGRAPHY_CARD as _t, Typography as vt } from "./typography/typography.types.js";
60
60
  import "./typography/index.js";
61
- export { e as BADGE_CARD, n as BOX_CARD, r as Box, i as Button, m as CONDITIONAL_CARD, u as Checkbox, h as Conditional, g as DATA_TABLE_ACTION, _ as DATA_TABLE_CARD, v as DATA_TABLE_ROW_DETAIL_CARD, Ce as DEF_ERROR_COLOR, we as DEF_EVENT_DURATION_SECONDS, Te as DEF_HEIGHT, Ee as DEF_OVERLAY_OPACITY, De as DEF_PASTE_FIRST_REMINDER, Oe as DEF_PASTE_TARGET_FILE_TYPES, ke as DEF_SUCCESS_COLOR, M as DROP_DOWN_MENU_ACTION, N as DROP_DOWN_MENU_CARD, y as DataTable, b as DataTableRowDetail, E as Dialog, P as DropDownMenu, R as FLEX_GRID_CARD, I as Field, z as FlexGrid, B as Form, c as FormContext, X as LIST_ACTION, Z as LIST_CARD, ee as LOADING_OVERLAY_CARD, ne as LOADING_SKELETON_CARD, Q as List, te as LoadingOverlay, re as LoadingSkeleton, ie as MENU_ACTION, ae as MENU_CARD, ce as MODE_TOGGLE_ACTION, le as MODE_TOGGLE_CARD, oe as Menu, ue as ModeToggle, fe as NAVBAR_SEARCH_ACTION, pe as NAVBAR_SEARCH_CARD, me as NavbarSearch, ve as PAGE_WITH_NAVBAR_ACTION, ye as PAGE_WITH_NAVBAR_CARD, Ae as PASTE_TARGET_ACTION, je as PASTE_TARGET_CARD, a as PI_BUTTON_ACTION, o as PI_BUTTON_CARD, d as PI_CHECKBOX_ACTION, f as PI_CHECKBOX_CARD, D as PI_DIALOG_ACTION, O as PI_DIALOG_CARD, L as PI_FIELD_CARD, V as PI_FORM_ACTION, H as PI_FORM_CARD, G as PI_INPUT_ACTION, K as PI_INPUT_CARD, Fe as PI_SELECT_ACTION, Ie as PI_SELECT_CARD, qe as PI_SWITCH_ACTION, Je as PI_SWITCH_CARD, tt as PI_TEXT_FIELD_ACTION, nt as PI_TEXT_FIELD_CARD, at as PI_TOAST_ACTION, ot as PI_TOAST_CARD, ft as PI_TOGGLE_GROUP_ACTION, pt as PI_TOGGLE_GROUP_CARD, be as PageWithNavbar, Me as PasteTarget, q as PiInput, Ve as STACK_CARD, Ue as STEPPER_ACTION, We as STEPPER_CARD, W as SdFramework, Se as SdPageWithNavbar, Ze as SdTabs, Le as Select, t as ShadBadge, He as Stack, Ge as Stepper, Ye as Switch, Qe as TABS_ACTION, $e as TABS_CARD, st as TOAST_OP_ACTION, gt as TYPOGRAPHY_CARD, rt as TextField, ct as Toast, mt as ToggleGroup, _t as Typography, lt as dispatchShowToast, Ne as onContentPasted, x as onDataTableHideDetail, S as onDataTablePageChanged, C as onDataTableRowClicked, w as onDataTableShowDetail, T as onDataTableSortChanged, k as onDialogClosed, A as onDialogOpenChanged, j as onDialogOpened, F as onDropDownMenuClicked, $ as onListItemClicked, se as onMenuClicked, de as onModeToggleChanged, he as onNavbarSearchFocus, ge as onNavbarSearchItems, _e as onNavbarSearchSubmit, xe as onPageWithNavbarNavigateTo, Pe as onPasteError, s as onPiButtonClicked, p as onPiCheckboxChanged, U as onPiFormSubmitted, J as onPiInputChanged, Y as onPiInputCommitted, Re as onPiSelectChanged, ze as onPiSelectClosed, Be as onPiSelectOpened, Xe as onPiSwitchChanged, it as onPiTextFieldChanged, ut as onPiToastClosed, ht as onPiToggleGroupChanged, dt as onShowToast, Ke as onStepperStepClicked, et as onTabsTabChanged, l as useFormContext };
61
+ export { e as BADGE_CARD, n as BOX_CARD, r as Box, i as Button, m as CONDITIONAL_CARD, u as Checkbox, h as Conditional, g as DATA_TABLE_ACTION, _ as DATA_TABLE_CARD, v as DATA_TABLE_ROW_DETAIL_CARD, Ce as DEF_ERROR_COLOR, we as DEF_EVENT_DURATION_SECONDS, Te as DEF_HEIGHT, Ee as DEF_OVERLAY_OPACITY, De as DEF_PASTE_FIRST_REMINDER, Oe as DEF_PASTE_TARGET_FILE_TYPES, ke as DEF_SUCCESS_COLOR, M as DROP_DOWN_MENU_ACTION, N as DROP_DOWN_MENU_CARD, y as DataTable, b as DataTableRowDetail, E as Dialog, P as DropDownMenu, R as FLEX_GRID_CARD, I as Field, z as FlexGrid, B as Form, c as FormContext, X as LIST_ACTION, Z as LIST_CARD, ee as LOADING_OVERLAY_CARD, ne as LOADING_SKELETON_CARD, Q as List, te as LoadingOverlay, re as LoadingSkeleton, ie as MENU_ACTION, ae as MENU_CARD, ce as MODE_TOGGLE_ACTION, le as MODE_TOGGLE_CARD, oe as Menu, ue as ModeToggle, fe as NAVBAR_SEARCH_ACTION, pe as NAVBAR_SEARCH_CARD, me as NavbarSearch, ve as PAGE_WITH_NAVBAR_ACTION, ye as PAGE_WITH_NAVBAR_CARD, Ae as PASTE_TARGET_ACTION, je as PASTE_TARGET_CARD, a as PI_BUTTON_ACTION, o as PI_BUTTON_CARD, d as PI_CHECKBOX_ACTION, f as PI_CHECKBOX_CARD, D as PI_DIALOG_ACTION, O as PI_DIALOG_CARD, L as PI_FIELD_CARD, V as PI_FORM_ACTION, H as PI_FORM_CARD, G as PI_INPUT_ACTION, K as PI_INPUT_CARD, Fe as PI_SELECT_ACTION, Ie as PI_SELECT_CARD, qe as PI_SWITCH_ACTION, Je as PI_SWITCH_CARD, nt as PI_TEXT_FIELD_ACTION, rt as PI_TEXT_FIELD_CARD, ot as PI_TOAST_ACTION, st as PI_TOAST_CARD, pt as PI_TOGGLE_GROUP_ACTION, mt as PI_TOGGLE_GROUP_CARD, be as PageWithNavbar, Me as PasteTarget, q as PiInput, Ve as STACK_CARD, Ue as STEPPER_ACTION, We as STEPPER_CARD, W as SdFramework, Se as SdPageWithNavbar, Ze as SdTabs, Le as Select, t as ShadBadge, He as Stack, Ge as Stepper, Ye as Switch, Qe as TABS_ACTION, $e as TABS_CARD, ct as TOAST_OP_ACTION, _t as TYPOGRAPHY_CARD, et as Tabs, it as TextField, lt as Toast, ht as ToggleGroup, vt as Typography, ut as dispatchShowToast, Ne as onContentPasted, x as onDataTableHideDetail, S as onDataTablePageChanged, C as onDataTableRowClicked, w as onDataTableShowDetail, T as onDataTableSortChanged, k as onDialogClosed, A as onDialogOpenChanged, j as onDialogOpened, F as onDropDownMenuClicked, $ as onListItemClicked, se as onMenuClicked, de as onModeToggleChanged, he as onNavbarSearchFocus, ge as onNavbarSearchItems, _e as onNavbarSearchSubmit, xe as onPageWithNavbarNavigateTo, Pe as onPasteError, s as onPiButtonClicked, p as onPiCheckboxChanged, U as onPiFormSubmitted, J as onPiInputChanged, Y as onPiInputCommitted, Re as onPiSelectChanged, ze as onPiSelectClosed, Be as onPiSelectOpened, Xe as onPiSwitchChanged, at as onPiTextFieldChanged, dt as onPiToastClosed, gt as onPiToggleGroupChanged, ft as onShowToast, Ke as onStepperStepClicked, tt as onTabsTabChanged, l as useFormContext };
@@ -0,0 +1,5 @@
1
+ import { default as React } from 'react';
2
+ import { PiCardProps } from '@pihanga2/core';
3
+ import { FileDropEvents, FileDropProps } from './fileDrop.types';
4
+ export declare function get_last_dropped(name: string): File | null;
5
+ export declare const FileDropComponent: (props: PiCardProps<FileDropProps, FileDropEvents>) => React.ReactNode;
@@ -0,0 +1,43 @@
1
+ export declare const FILE_DROP_CARD = "shad/file-drop";
2
+ export declare const FileDrop: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<FileDropProps<Record<string, unknown>>, S, FileDropEvents>) => import('@pihanga2/core').PiCardDef;
3
+ export declare const FILE_DROP_ACTION: {
4
+ ERROR: string;
5
+ FILE_DROPPED: string;
6
+ };
7
+ export declare const onFileDropped: <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
+ } & FileDroppedEvent>) => void;
10
+ export declare const onFileDropError: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
11
+ cardID: string;
12
+ } & FileDropErrorEvent>) => void;
13
+ export type FileDropProps<S = Record<string, unknown>> = {
14
+ /** Accepted file extensions, e.g. ["JPG", "PNG", "PDF"]. Defaults to ["JPG", "PNG", "GIF"]. */
15
+ fileTypes?: string[];
16
+ /** Heading shown inside the drop zone. */
17
+ title?: string;
18
+ /** Secondary text shown inside the drop zone. */
19
+ description?: string;
20
+ /** When true, shows a progress bar instead of the drop zone. */
21
+ showProgress?: boolean;
22
+ /** Inline styles applied to the drop zone wrapper. */
23
+ dropStyle?: Record<string, unknown>;
24
+ /** Inline styles applied to the progress bar container. */
25
+ progressStyle?: Record<string, unknown>;
26
+ /** Current upload progress (0–100). Only used when `showProgress` is true. */
27
+ progress?: number;
28
+ style?: S;
29
+ className?: string;
30
+ };
31
+ export declare const DEF_FILE_DROP_FILE_TYPES: string[];
32
+ export type FileDroppedEvent = {
33
+ name: string;
34
+ size: number;
35
+ type: string;
36
+ };
37
+ export type FileDropErrorEvent = {
38
+ error: string;
39
+ };
40
+ export type FileDropEvents = {
41
+ onFileDropped: FileDroppedEvent;
42
+ onError: FileDropErrorEvent;
43
+ };
@@ -0,0 +1,2 @@
1
+ export * from './fileDrop.types';
2
+ export { get_last_dropped } from './fileDrop.component';
package/cards/icons.js CHANGED
@@ -2,14 +2,18 @@ import e from "react";
2
2
  //#region src/cards/icons.ts
3
3
  window._PihangaIcons = window._PihangaIcons || { name2icon: {} };
4
4
  var t = window._PihangaIcons.name2icon;
5
- function n(e) {
5
+ function n(e, n) {
6
+ if (t[e] !== void 0) throw Error(`icon '${e}' already registered`);
7
+ return t[e] = n, e;
8
+ }
9
+ function r(e) {
6
10
  return t[e];
7
11
  }
8
- function r(n, r) {
12
+ function i(n, r) {
9
13
  let i = t[n];
10
14
  return i ? e.createElement(i, r) : null;
11
15
  }
12
16
  //#endregion
13
- export { r as getIcon, n as getIconElement };
17
+ export { i as getIcon, r as getIconElement, n as registerIcon };
14
18
 
15
19
  //# sourceMappingURL=icons.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","names":[],"sources":["../../src/cards/icons.ts"],"sourcesContent":["import React from \"react\";\n\ntype G = {\n name2icon: {[name: string]: React.ElementType};\n};\n\ndeclare global {\n interface Window {\n _PihangaIcons: G;\n }\n}\n\nwindow._PihangaIcons = window._PihangaIcons || {\n name2icon: {},\n};\n\nconst name2icon = window._PihangaIcons.name2icon;\n\n\n\nexport function registerIcon(name: string, el: React.ElementType): string {\n if (name2icon[name] !== undefined) {\n throw new Error(`icon '${name}' already registered`);\n }\n name2icon[name] = el;\n return name;\n}\n\nexport function getIconElement(name: string): React.ElementType | undefined {\n return name2icon[name];\n}\n\n// can't figure out what the proper return type is, SVvgIconT does\n// NOT work with <IconButton>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getIcon(name: string, props?: any): React.ReactNode {\n const icon = name2icon[name];\n if (!icon) return null;\n const el = React.createElement(icon, props);\n return el;\n}\n"],"mappings":";;AAYA,OAAO,gBAAgB,OAAO,iBAAiB,EAC7C,WAAW,CAAC,EACd;AAEA,IAAM,IAAY,OAAO,cAAc;AAYvC,SAAgB,EAAe,GAA6C;CAC1E,OAAO,EAAU;AACnB;AAKA,SAAgB,EAAQ,GAAc,GAA8B;CAClE,IAAM,IAAO,EAAU;CAGvB,OAFK,IACM,EAAM,cAAc,GAAM,CAC9B,IAFW;AAGpB"}
1
+ {"version":3,"file":"icons.js","names":[],"sources":["../../src/cards/icons.ts"],"sourcesContent":["import React from \"react\";\n\ntype G = {\n name2icon: {[name: string]: React.ElementType};\n};\n\ndeclare global {\n interface Window {\n _PihangaIcons: G;\n }\n}\n\nwindow._PihangaIcons = window._PihangaIcons || {\n name2icon: {},\n};\n\nconst name2icon = window._PihangaIcons.name2icon;\n\n\n\nexport function registerIcon(name: string, el: React.ElementType): string {\n if (name2icon[name] !== undefined) {\n throw new Error(`icon '${name}' already registered`);\n }\n name2icon[name] = el;\n return name;\n}\n\nexport function getIconElement(name: string): React.ElementType | undefined {\n return name2icon[name];\n}\n\n// can't figure out what the proper return type is, SVvgIconT does\n// NOT work with <IconButton>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getIcon(name: string, props?: any): React.ReactNode {\n const icon = name2icon[name];\n if (!icon) return null;\n const el = React.createElement(icon, props);\n return el;\n}\n"],"mappings":";;AAYA,OAAO,gBAAgB,OAAO,iBAAiB,EAC7C,WAAW,CAAC,EACd;AAEA,IAAM,IAAY,OAAO,cAAc;AAIvC,SAAgB,EAAa,GAAc,GAA+B;CACxE,IAAI,EAAU,OAAU,KAAA,GACtB,MAAU,MAAM,SAAS,EAAK,qBAAqB;CAGrD,OADA,EAAU,KAAQ,GACX;AACT;AAEA,SAAgB,EAAe,GAA6C;CAC1E,OAAO,EAAU;AACnB;AAKA,SAAgB,EAAQ,GAAc,GAA8B;CAClE,IAAM,IAAO,EAAU;CAGvB,OAFK,IACM,EAAM,cAAc,GAAM,CAC9B,IAFW;AAGpB"}
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -1,5 +1,23 @@
1
1
  import { PiCardRef } from '@pihanga2/core';
2
- export declare const STACK_CARD = "shad/stack";
2
+ import { AlignItemsT } from '../types';
3
+ export declare const STACK_CARD = "pi/stack";
4
+ /**
5
+ * Factory function for declaring a `stack` card instance.
6
+ *
7
+ * ```ts
8
+ * import {registerCard} from "@pihanga2/core";
9
+ * import {Stack} from "@/cards/stack";
10
+ *
11
+ * registerCard("myApp/toolbar", Stack({
12
+ * direction: "row",
13
+ * spacing: 2,
14
+ * alignItems: "center",
15
+ * justifyContent: "space-between",
16
+ * content: ["myApp/logo", "myApp/navLinks", "myApp/userMenu"],
17
+ * }));
18
+ * ```
19
+ */
20
+ export declare const Stack: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<StackProps<object>, S, {}>) => import('@pihanga2/core').PiCardDef;
3
21
  /**
4
22
  * CSS `flex-direction` values supported by the Stack card.
5
23
  */
@@ -8,10 +26,6 @@ export type DirectionT = "column-reverse" | "column" | "row-reverse" | "row";
8
26
  * CSS `justify-content` values supported by the Stack card.
9
27
  */
10
28
  export type JustifyContentT = "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | "space-evenly";
11
- /**
12
- * CSS `align-items` values supported by the Stack card.
13
- */
14
- export type AlignItemsT = "normal" | "stretch" | "center" | "flex-start" | "flex-end" | "start" | "end" | "baseline" | "initial" | "inherit";
15
29
  export type StackProps<S = object> = {
16
30
  /** Ordered list of child card refs to render */
17
31
  content: PiCardRef[];
@@ -28,20 +42,3 @@ export type StackProps<S = object> = {
28
42
  /** Card style object (use the `shad` key for Tailwind-compatible overrides) */
29
43
  style?: S;
30
44
  };
31
- /**
32
- * Factory function for declaring a `shad/stack` card instance.
33
- *
34
- * ```ts
35
- * import {registerCard} from "@pihanga2/core";
36
- * import {Stack} from "@/cards/stack";
37
- *
38
- * registerCard("myApp/toolbar", Stack({
39
- * direction: "row",
40
- * spacing: 2,
41
- * alignItems: "center",
42
- * justifyContent: "space-between",
43
- * content: ["myApp/logo", "myApp/navLinks", "myApp/userMenu"],
44
- * }));
45
- * ```
46
- */
47
- export declare const Stack: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<StackProps<object>, S, {}>) => import('@pihanga2/core').PiCardDef;
@@ -1,6 +1,6 @@
1
1
  import { createCardDeclaration as e } from "@pihanga2/core";
2
2
  //#region src/cards/stack/stack.types.ts
3
- var t = "shad/stack", n = e(t);
3
+ var t = "pi/stack", n = e(t);
4
4
  //#endregion
5
5
  export { t as STACK_CARD, n as Stack };
6
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"stack.types.js","names":[],"sources":["../../../src/cards/stack/stack.types.ts"],"sourcesContent":["import {type PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\n\nexport const STACK_CARD = \"shad/stack\";\n\n/**\n * CSS `flex-direction` values supported by the Stack card.\n */\nexport type DirectionT = \"column-reverse\" | \"column\" | \"row-reverse\" | \"row\";\n\n/**\n * CSS `justify-content` values supported by the Stack card.\n */\nexport type JustifyContentT =\n | \"flex-start\"\n | \"center\"\n | \"flex-end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n\n/**\n * CSS `align-items` values supported by the Stack card.\n */\nexport type AlignItemsT =\n | \"normal\"\n | \"stretch\"\n | \"center\"\n | \"flex-start\"\n | \"flex-end\"\n | \"start\"\n | \"end\"\n | \"baseline\"\n | \"initial\"\n | \"inherit\";\n\nexport type StackProps<S = object> = {\n /** Ordered list of child card refs to render */\n content: PiCardRef[];\n\n /** Flex direction — defaults to `\"column\"` */\n direction?: DirectionT;\n /** Optional card ref rendered as a separator between children */\n divider?: PiCardRef;\n /** Tailwind gap spacing units between children */\n spacing?: number;\n\n justifyContent?: JustifyContentT;\n alignItems?: AlignItemsT;\n\n /** Additional Tailwind utility classes */\n className?: string;\n /** Card style object (use the `shad` key for Tailwind-compatible overrides) */\n style?: S;\n};\n\n/**\n * Factory function for declaring a `shad/stack` card instance.\n *\n * ```ts\n * import {registerCard} from \"@pihanga2/core\";\n * import {Stack} from \"@/cards/stack\";\n *\n * registerCard(\"myApp/toolbar\", Stack({\n * direction: \"row\",\n * spacing: 2,\n * alignItems: \"center\",\n * justifyContent: \"space-between\",\n * content: [\"myApp/logo\", \"myApp/navLinks\", \"myApp/userMenu\"],\n * }));\n * ```\n */\nexport const Stack = createCardDeclaration<StackProps>(STACK_CARD);\n"],"mappings":";;AAEA,IAAa,IAAa,cAqEb,IAAQ,EAAkC,CAAU"}
1
+ {"version":3,"file":"stack.types.js","names":[],"sources":["../../../src/cards/stack/stack.types.ts"],"sourcesContent":["import {type PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\nimport {AlignItemsT} from \"../types\";\n\nexport const STACK_CARD = \"pi/stack\";\n\n/**\n * Factory function for declaring a `stack` card instance.\n *\n * ```ts\n * import {registerCard} from \"@pihanga2/core\";\n * import {Stack} from \"@/cards/stack\";\n *\n * registerCard(\"myApp/toolbar\", Stack({\n * direction: \"row\",\n * spacing: 2,\n * alignItems: \"center\",\n * justifyContent: \"space-between\",\n * content: [\"myApp/logo\", \"myApp/navLinks\", \"myApp/userMenu\"],\n * }));\n * ```\n */\nexport const Stack = createCardDeclaration<StackProps>(STACK_CARD);\n\n/**\n * CSS `flex-direction` values supported by the Stack card.\n */\nexport type DirectionT = \"column-reverse\" | \"column\" | \"row-reverse\" | \"row\";\n\n/**\n * CSS `justify-content` values supported by the Stack card.\n */\nexport type JustifyContentT =\n | \"flex-start\"\n | \"center\"\n | \"flex-end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n\nexport type StackProps<S = object> = {\n /** Ordered list of child card refs to render */\n content: PiCardRef[];\n\n /** Flex direction — defaults to `\"column\"` */\n direction?: DirectionT;\n /** Optional card ref rendered as a separator between children */\n divider?: PiCardRef;\n /** Tailwind gap spacing units between children */\n spacing?: number;\n\n justifyContent?: JustifyContentT;\n alignItems?: AlignItemsT;\n\n /** Additional Tailwind utility classes */\n className?: string;\n /** Card style object (use the `shad` key for Tailwind-compatible overrides) */\n style?: S;\n};\n"],"mappings":";;AAGA,IAAa,IAAa,YAkBb,IAAQ,EAAkC,CAAU"}
@@ -1,13 +1,13 @@
1
1
  import { TabsComponent as e } from "./tabs.component.js";
2
- import { SdTabs as t, TABS_ACTION as n, TABS_CARD as r, onTabsTabChanged as i } from "./tabs.types.js";
3
- import { registerCardComponent as a } from "@pihanga2/core";
2
+ import { SdTabs as t, TABS_ACTION as n, TABS_CARD as r, Tabs as i, onTabsTabChanged as a } from "./tabs.types.js";
3
+ import { registerCardComponent as o } from "@pihanga2/core";
4
4
  //#region src/cards/tabs/index.ts
5
- a({
5
+ o({
6
6
  name: r,
7
7
  component: e,
8
8
  events: { onTabChanged: n.TABCHANGED }
9
9
  });
10
10
  //#endregion
11
- export { t as SdTabs, n as TABS_ACTION, r as TABS_CARD, i as onTabsTabChanged };
11
+ export { t as SdTabs, n as TABS_ACTION, r as TABS_CARD, i as Tabs, a as onTabsTabChanged };
12
12
 
13
13
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,7 @@
1
1
  import { PiCardRef } from '@pihanga2/core';
2
2
  export declare const TABS_CARD = "shad/tabs";
3
+ export declare const Tabs: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<TabsProps, S, TabsEvents>) => import('@pihanga2/core').PiCardDef;
4
+ /** @deprecated Use {@link Tabs} instead. */
3
5
  export declare const SdTabs: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<TabsProps, S, TabsEvents>) => import('@pihanga2/core').PiCardDef;
4
6
  export declare const TABS_ACTION: {
5
7
  TABCHANGED: string;
@@ -1,7 +1,7 @@
1
1
  import { createCardDeclaration as e, createOnAction as t, registerActions as n } from "@pihanga2/core";
2
2
  //#region src/cards/tabs/tabs.types.ts
3
- var r = "shad/tabs", i = e(r), a = n(r, ["tabChanged"]), o = t(a.TABCHANGED);
3
+ var r = "shad/tabs", i = e(r), a = i, o = n(r, ["tabChanged"]), s = t(o.TABCHANGED);
4
4
  //#endregion
5
- export { i as SdTabs, a as TABS_ACTION, r as TABS_CARD, o as onTabsTabChanged };
5
+ export { a as SdTabs, o as TABS_ACTION, r as TABS_CARD, i as Tabs, s as onTabsTabChanged };
6
6
 
7
7
  //# sourceMappingURL=tabs.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.types.js","names":[],"sources":["../../../src/cards/tabs/tabs.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n type PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const TABS_CARD = \"shad/tabs\";\n\nexport const SdTabs = createCardDeclaration<TabsProps, TabsEvents>(TABS_CARD);\n\nexport const TABS_ACTION = registerActions(TABS_CARD, [\"tabChanged\"]);\n\nexport const onTabsTabChanged = createOnAction<TabsTabChangedEvent>(\n TABS_ACTION.TABCHANGED,\n);\n\n// ─── Tab item definition ──────────────────────────────────────────────────────\n\n/**\n * A single tab entry in the tabs component.\n */\nexport type TabItem = {\n /** Unique identifier used for controlled value and events. */\n id: string;\n\n /**\n * The label displayed on the tab trigger.\n * Can be a plain string or a PiCardRef for custom/rich tab labels.\n */\n title: string | PiCardRef;\n\n /**\n * The Pihanga card rendered as the body of this tab when it is active.\n */\n contentCard: PiCardRef;\n\n /** When true the tab trigger is rendered as disabled. */\n disabled?: boolean;\n};\n\n// ─── Card props ───────────────────────────────────────────────────────────────\n\nexport type TabsProps = {\n /** Ordered list of tab definitions. */\n tabs: TabItem[];\n\n /**\n * Controlled: the currently active tab id.\n * Must be provided (or supplied via a state mapper) when selfManaged is\n * false (the default).\n */\n value?: string;\n\n /**\n * Uncontrolled initial active tab id.\n * Used as the initial value in self-managed mode when value is not set;\n * falls back to the first tab id if omitted.\n */\n defaultValue?: string;\n\n /**\n * When true, the component manages its own active tab state internally.\n * The onTabChanged event is still dispatched on every change so external\n * reducers can observe the selection.\n *\n * When false (default), value fully controls the displayed tab.\n * @default false\n */\n selfManaged?: boolean;\n\n /**\n * Layout orientation of the tab list.\n * Passed directly to the Radix Tabs primitive.\n * @default \"horizontal\"\n */\n orientation?: \"horizontal\" | \"vertical\";\n\n /** Additional Tailwind/CSS classes applied to the root Tabs element. */\n className?: string;\n\n /** Additional classes applied to the TabsList element. */\n listClassName?: string;\n\n /** Additional classes applied to each TabsContent element. */\n contentClassName?: string;\n};\n\n// ─── Events ───────────────────────────────────────────────────────────────────\n\nexport type TabsTabChangedEvent = {\n /** The id of the newly selected tab. */\n tabId: string;\n};\n\nexport type TabsEvents = {\n /** Fired whenever the user selects a different tab. */\n onTabChanged: TabsTabChangedEvent;\n};\n"],"mappings":";;AAOA,IAAa,IAAY,aAEZ,IAAS,EAA6C,CAAS,GAE/D,IAAc,EAAgB,GAAW,CAAC,YAAY,CAAC,GAEvD,IAAmB,EAC9B,EAAY,UACd"}
1
+ {"version":3,"file":"tabs.types.js","names":[],"sources":["../../../src/cards/tabs/tabs.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n type PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const TABS_CARD = \"shad/tabs\";\n\nexport const Tabs = createCardDeclaration<TabsProps, TabsEvents>(TABS_CARD);\n\n/** @deprecated Use {@link Tabs} instead. */\nexport const SdTabs = Tabs;\n\nexport const TABS_ACTION = registerActions(TABS_CARD, [\"tabChanged\"]);\n\nexport const onTabsTabChanged = createOnAction<TabsTabChangedEvent>(\n TABS_ACTION.TABCHANGED,\n);\n\n// ─── Tab item definition ──────────────────────────────────────────────────────\n\n/**\n * A single tab entry in the tabs component.\n */\nexport type TabItem = {\n /** Unique identifier used for controlled value and events. */\n id: string;\n\n /**\n * The label displayed on the tab trigger.\n * Can be a plain string or a PiCardRef for custom/rich tab labels.\n */\n title: string | PiCardRef;\n\n /**\n * The Pihanga card rendered as the body of this tab when it is active.\n */\n contentCard: PiCardRef;\n\n /** When true the tab trigger is rendered as disabled. */\n disabled?: boolean;\n};\n\n// ─── Card props ───────────────────────────────────────────────────────────────\n\nexport type TabsProps = {\n /** Ordered list of tab definitions. */\n tabs: TabItem[];\n\n /**\n * Controlled: the currently active tab id.\n * Must be provided (or supplied via a state mapper) when selfManaged is\n * false (the default).\n */\n value?: string;\n\n /**\n * Uncontrolled initial active tab id.\n * Used as the initial value in self-managed mode when value is not set;\n * falls back to the first tab id if omitted.\n */\n defaultValue?: string;\n\n /**\n * When true, the component manages its own active tab state internally.\n * The onTabChanged event is still dispatched on every change so external\n * reducers can observe the selection.\n *\n * When false (default), value fully controls the displayed tab.\n * @default false\n */\n selfManaged?: boolean;\n\n /**\n * Layout orientation of the tab list.\n * Passed directly to the Radix Tabs primitive.\n * @default \"horizontal\"\n */\n orientation?: \"horizontal\" | \"vertical\";\n\n /** Additional Tailwind/CSS classes applied to the root Tabs element. */\n className?: string;\n\n /** Additional classes applied to the TabsList element. */\n listClassName?: string;\n\n /** Additional classes applied to each TabsContent element. */\n contentClassName?: string;\n};\n\n// ─── Events ───────────────────────────────────────────────────────────────────\n\nexport type TabsTabChangedEvent = {\n /** The id of the newly selected tab. */\n tabId: string;\n};\n\nexport type TabsEvents = {\n /** Fired whenever the user selects a different tab. */\n onTabChanged: TabsTabChangedEvent;\n};\n"],"mappings":";;AAOA,IAAa,IAAY,aAEZ,IAAO,EAA6C,CAAS,GAG7D,IAAS,GAET,IAAc,EAAgB,GAAW,CAAC,YAAY,CAAC,GAEvD,IAAmB,EAC9B,EAAY,UACd"}
package/cards/types.d.ts CHANGED
@@ -70,3 +70,7 @@ export type ColorT = string;
70
70
  * registry) or an arbitrary Tailwind-class string for inline SVG icons.
71
71
  */
72
72
  export type DecoratorT = string;
73
+ /**
74
+ * CSS `align-items` values supported by the Box & Stack card.
75
+ */
76
+ export type AlignItemsT = "normal" | "stretch" | "center" | "flex-start" | "flex-end" | "start" | "end" | "baseline" | "initial" | "inherit";
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../src/cards/types.ts"],"sourcesContent":["/**\n * Screen size breakpoints matching Tailwind CSS defaults.\n *\n * Used with {@link SizeMap} to render different cards (or none at all)\n * depending on the viewport width.\n */\nexport enum ScreenSize {\n XS = \"xs\", // default / < 640px\n SM = \"sm\", // ≥ 640px\n MD = \"md\", // ≥ 768px\n LG = \"lg\", // ≥ 1024px\n XL = \"xl\", // ≥ 1280px\n XXL = \"2xl\", // ≥ 1536px\n}\n\n/**\n * Ascending order of breakpoints — used for cascade resolution.\n * @internal\n */\nexport const SCREEN_SIZE_ORDER: ScreenSize[] = [\n ScreenSize.XS,\n ScreenSize.SM,\n ScreenSize.MD,\n ScreenSize.LG,\n ScreenSize.XL,\n ScreenSize.XXL,\n];\n\n/**\n * Minimum viewport widths (px) for each breakpoint.\n * @internal\n */\nexport const SCREEN_SIZE_WIDTHS: Record<ScreenSize, number> = {\n [ScreenSize.XS]: 0,\n [ScreenSize.SM]: 640,\n [ScreenSize.MD]: 768,\n [ScreenSize.LG]: 1024,\n [ScreenSize.XL]: 1280,\n [ScreenSize.XXL]: 1536,\n};\n\n/**\n * Map a value {@link T} to specific screen-size breakpoints.\n *\n * Resolution follows a **mobile-first cascade**: the entry with the\n * largest breakpoint that is ≤ the current viewport size wins.\n *\n * ```ts\n * // Show \"desktopCard\" on md and above, nothing on xs/sm:\n * { [ScreenSize.MD]: \"desktopCard\" }\n *\n * // Show a different card per breakpoint:\n * { [ScreenSize.XS]: \"mobileCard\", [ScreenSize.MD]: \"desktopCard\" }\n *\n * // Explicitly hide on md and above:\n * { [ScreenSize.XS]: \"card\", [ScreenSize.MD]: null }\n * ```\n *\n * Set `default` as a final fallback when no breakpoint entry matches.\n */\nexport type SizeMap<T> = Partial<Record<ScreenSize, T | null>> & {\n default?: T | null;\n};\n\n// ---------------------------------------------------------------------------\n// Shadcn / Tailwind-native shared primitive types\n//\n// These types replace what was previously imported from `@pihanga2/cards` and\n// are expressed in terms of Shadcn's design system and Tailwind utility tokens.\n// ---------------------------------------------------------------------------\n\n/**\n * Shadcn button / badge visual variant.\n *\n * Maps directly to the `variant` prop accepted by `@/components/ui/button`\n * and `@/components/ui/badge`.\n */\nexport type VariantT =\n | \"default\"\n | \"destructive\"\n | \"outline\"\n | \"secondary\"\n | \"ghost\"\n | \"link\";\n\n/**\n * Shadcn component size token.\n *\n * Maps directly to the `size` prop accepted by `@/components/ui/button`.\n */\nexport type SizeT = \"default\" | \"sm\" | \"lg\" | \"icon\";\n\n/**\n * Tailwind colour token (e.g. `\"red\"`, `\"emerald\"`, `\"sky\"`) or an arbitrary\n * CSS colour string. Kept as `string` so consumers can pass any Tailwind\n * palette key without being locked to a finite union.\n */\nexport type ColorT = string;\n\n/**\n * A decorator displayed before or after a button / menu-item label.\n *\n * Expressed as a registered icon name (resolved at render time via the icon\n * registry) or an arbitrary Tailwind-class string for inline SVG icons.\n */\nexport type DecoratorT = string;\n"],"mappings":";AAMA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,MAAA;AACF,EAAA,CAAA,CAAA,GAMa,IAAkC;;;;;;;AAO/C,GAMa,IAAiD;KAC3C;KACA;KACA;KACA;KACA;QACC;AACpB"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/cards/types.ts"],"sourcesContent":["/**\n * Screen size breakpoints matching Tailwind CSS defaults.\n *\n * Used with {@link SizeMap} to render different cards (or none at all)\n * depending on the viewport width.\n */\nexport enum ScreenSize {\n XS = \"xs\", // default / < 640px\n SM = \"sm\", // ≥ 640px\n MD = \"md\", // ≥ 768px\n LG = \"lg\", // ≥ 1024px\n XL = \"xl\", // ≥ 1280px\n XXL = \"2xl\", // ≥ 1536px\n}\n\n/**\n * Ascending order of breakpoints — used for cascade resolution.\n * @internal\n */\nexport const SCREEN_SIZE_ORDER: ScreenSize[] = [\n ScreenSize.XS,\n ScreenSize.SM,\n ScreenSize.MD,\n ScreenSize.LG,\n ScreenSize.XL,\n ScreenSize.XXL,\n];\n\n/**\n * Minimum viewport widths (px) for each breakpoint.\n * @internal\n */\nexport const SCREEN_SIZE_WIDTHS: Record<ScreenSize, number> = {\n [ScreenSize.XS]: 0,\n [ScreenSize.SM]: 640,\n [ScreenSize.MD]: 768,\n [ScreenSize.LG]: 1024,\n [ScreenSize.XL]: 1280,\n [ScreenSize.XXL]: 1536,\n};\n\n/**\n * Map a value {@link T} to specific screen-size breakpoints.\n *\n * Resolution follows a **mobile-first cascade**: the entry with the\n * largest breakpoint that is ≤ the current viewport size wins.\n *\n * ```ts\n * // Show \"desktopCard\" on md and above, nothing on xs/sm:\n * { [ScreenSize.MD]: \"desktopCard\" }\n *\n * // Show a different card per breakpoint:\n * { [ScreenSize.XS]: \"mobileCard\", [ScreenSize.MD]: \"desktopCard\" }\n *\n * // Explicitly hide on md and above:\n * { [ScreenSize.XS]: \"card\", [ScreenSize.MD]: null }\n * ```\n *\n * Set `default` as a final fallback when no breakpoint entry matches.\n */\nexport type SizeMap<T> = Partial<Record<ScreenSize, T | null>> & {\n default?: T | null;\n};\n\n// ---------------------------------------------------------------------------\n// Shadcn / Tailwind-native shared primitive types\n//\n// These types replace what was previously imported from `@pihanga2/cards` and\n// are expressed in terms of Shadcn's design system and Tailwind utility tokens.\n// ---------------------------------------------------------------------------\n\n/**\n * Shadcn button / badge visual variant.\n *\n * Maps directly to the `variant` prop accepted by `@/components/ui/button`\n * and `@/components/ui/badge`.\n */\nexport type VariantT =\n | \"default\"\n | \"destructive\"\n | \"outline\"\n | \"secondary\"\n | \"ghost\"\n | \"link\";\n\n/**\n * Shadcn component size token.\n *\n * Maps directly to the `size` prop accepted by `@/components/ui/button`.\n */\nexport type SizeT = \"default\" | \"sm\" | \"lg\" | \"icon\";\n\n/**\n * Tailwind colour token (e.g. `\"red\"`, `\"emerald\"`, `\"sky\"`) or an arbitrary\n * CSS colour string. Kept as `string` so consumers can pass any Tailwind\n * palette key without being locked to a finite union.\n */\nexport type ColorT = string;\n\n/**\n * A decorator displayed before or after a button / menu-item label.\n *\n * Expressed as a registered icon name (resolved at render time via the icon\n * registry) or an arbitrary Tailwind-class string for inline SVG icons.\n */\nexport type DecoratorT = string;\n\n/**\n * CSS `align-items` values supported by the Box & Stack card.\n */\nexport type AlignItemsT =\n | \"normal\"\n | \"stretch\"\n | \"center\"\n | \"flex-start\"\n | \"flex-end\"\n | \"start\"\n | \"end\"\n | \"baseline\"\n | \"initial\"\n | \"inherit\";\n"],"mappings":";AAMA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,KAAA,MACA,EAAA,MAAA;AACF,EAAA,CAAA,CAAA,GAMa,IAAkC;;;;;;;AAO/C,GAMa,IAAiD;KAC3C;KACA;KACA;KACA;KACA;QACC;AACpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pihanga2/shadcn",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
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": {
@@ -127,6 +127,14 @@
127
127
  "./cards/typography": {
128
128
  "import": "./cards/typography/index.js",
129
129
  "types": "./cards/typography/index.d.ts"
130
+ },
131
+ "./cards/types": {
132
+ "import": "./cards/types.js",
133
+ "types": "./cards/types.d.ts"
134
+ },
135
+ "./cards/icons": {
136
+ "import": "./cards/icons.js",
137
+ "types": "./cards/icons.d.ts"
130
138
  }
131
139
  },
132
140
  "main": "./cards/core-index.js",
@@ -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}@layer theme{@theme default{--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --color-red-50: oklch(97.1% .013 17.38); --color-red-100: oklch(93.6% .032 17.717); --color-red-200: oklch(88.5% .062 18.334); --color-red-300: oklch(80.8% .114 19.571); --color-red-400: oklch(70.4% .191 22.216); --color-red-500: oklch(63.7% .237 25.331); --color-red-600: oklch(57.7% .245 27.325); --color-red-700: oklch(50.5% .213 27.518); --color-red-800: oklch(44.4% .177 26.899); --color-red-900: oklch(39.6% .141 25.723); --color-red-950: oklch(25.8% .092 26.042); --color-orange-50: oklch(98% .016 73.684); --color-orange-100: oklch(95.4% .038 75.164); --color-orange-200: oklch(90.1% .076 70.697); --color-orange-300: oklch(83.7% .128 66.29); --color-orange-400: oklch(75% .183 55.934); --color-orange-500: oklch(70.5% .213 47.604); --color-orange-600: oklch(64.6% .222 41.116); --color-orange-700: oklch(55.3% .195 38.402); --color-orange-800: oklch(47% .157 37.304); --color-orange-900: oklch(40.8% .123 38.172); --color-orange-950: oklch(26.6% .079 36.259); --color-amber-50: oklch(98.7% .022 95.277); --color-amber-100: oklch(96.2% .059 95.617); --color-amber-200: oklch(92.4% .12 95.746); --color-amber-300: oklch(87.9% .169 91.605); --color-amber-400: oklch(82.8% .189 84.429); --color-amber-500: oklch(76.9% .188 70.08); --color-amber-600: oklch(66.6% .179 58.318); --color-amber-700: oklch(55.5% .163 48.998); --color-amber-800: oklch(47.3% .137 46.201); --color-amber-900: oklch(41.4% .112 45.904); --color-amber-950: oklch(27.9% .077 45.635); --color-yellow-50: oklch(98.7% .026 102.212); --color-yellow-100: oklch(97.3% .071 103.193); --color-yellow-200: oklch(94.5% .129 101.54); --color-yellow-300: oklch(90.5% .182 98.111); --color-yellow-400: oklch(85.2% .199 91.936); --color-yellow-500: oklch(79.5% .184 86.047); --color-yellow-600: oklch(68.1% .162 75.834); --color-yellow-700: oklch(55.4% .135 66.442); --color-yellow-800: oklch(47.6% .114 61.907); --color-yellow-900: oklch(42.1% .095 57.708); --color-yellow-950: oklch(28.6% .066 53.813); --color-lime-50: oklch(98.6% .031 120.757); --color-lime-100: oklch(96.7% .067 122.328); --color-lime-200: oklch(93.8% .127 124.321); --color-lime-300: oklch(89.7% .196 126.665); --color-lime-400: oklch(84.1% .238 128.85); --color-lime-500: oklch(76.8% .233 130.85); --color-lime-600: oklch(64.8% .2 131.684); --color-lime-700: oklch(53.2% .157 131.589); --color-lime-800: oklch(45.3% .124 130.933); --color-lime-900: oklch(40.5% .101 131.063); --color-lime-950: oklch(27.4% .072 132.109); --color-green-50: oklch(98.2% .018 155.826); --color-green-100: oklch(96.2% .044 156.743); --color-green-200: oklch(92.5% .084 155.995); --color-green-300: oklch(87.1% .15 154.449); --color-green-400: oklch(79.2% .209 151.711); --color-green-500: oklch(72.3% .219 149.579); --color-green-600: oklch(62.7% .194 149.214); --color-green-700: oklch(52.7% .154 150.069); --color-green-800: oklch(44.8% .119 151.328); --color-green-900: oklch(39.3% .095 152.535); --color-green-950: oklch(26.6% .065 152.934); --color-emerald-50: oklch(97.9% .021 166.113); --color-emerald-100: oklch(95% .052 163.051); --color-emerald-200: oklch(90.5% .093 164.15); --color-emerald-300: oklch(84.5% .143 164.978); --color-emerald-400: oklch(76.5% .177 163.223); --color-emerald-500: oklch(69.6% .17 162.48); --color-emerald-600: oklch(59.6% .145 163.225); --color-emerald-700: oklch(50.8% .118 165.612); --color-emerald-800: oklch(43.2% .095 166.913); --color-emerald-900: oklch(37.8% .077 168.94); --color-emerald-950: oklch(26.2% .051 172.552); --color-teal-50: oklch(98.4% .014 180.72); --color-teal-100: oklch(95.3% .051 180.801); --color-teal-200: oklch(91% .096 180.426); --color-teal-300: oklch(85.5% .138 181.071); --color-teal-400: oklch(77.7% .152 181.912); --color-teal-500: oklch(70.4% .14 182.503); --color-teal-600: oklch(60% .118 184.704); --color-teal-700: oklch(51.1% .096 186.391); --color-teal-800: oklch(43.7% .078 188.216); --color-teal-900: oklch(38.6% .063 188.416); --color-teal-950: oklch(27.7% .046 192.524); --color-cyan-50: oklch(98.4% .019 200.873); --color-cyan-100: oklch(95.6% .045 203.388); --color-cyan-200: oklch(91.7% .08 205.041); --color-cyan-300: oklch(86.5% .127 207.078); --color-cyan-400: oklch(78.9% .154 211.53); --color-cyan-500: oklch(71.5% .143 215.221); --color-cyan-600: oklch(60.9% .126 221.723); --color-cyan-700: oklch(52% .105 223.128); --color-cyan-800: oklch(45% .085 224.283); --color-cyan-900: oklch(39.8% .07 227.392); --color-cyan-950: oklch(30.2% .056 229.695); --color-sky-50: oklch(97.7% .013 236.62); --color-sky-100: oklch(95.1% .026 236.824); --color-sky-200: oklch(90.1% .058 230.902); --color-sky-300: oklch(82.8% .111 230.318); --color-sky-400: oklch(74.6% .16 232.661); --color-sky-500: oklch(68.5% .169 237.323); --color-sky-600: oklch(58.8% .158 241.966); --color-sky-700: oklch(50% .134 242.749); --color-sky-800: oklch(44.3% .11 240.79); --color-sky-900: oklch(39.1% .09 240.876); --color-sky-950: oklch(29.3% .066 243.157); --color-blue-50: oklch(97% .014 254.604); --color-blue-100: oklch(93.2% .032 255.585); --color-blue-200: oklch(88.2% .059 254.128); --color-blue-300: oklch(80.9% .105 251.813); --color-blue-400: oklch(70.7% .165 254.624); --color-blue-500: oklch(62.3% .214 259.815); --color-blue-600: oklch(54.6% .245 262.881); --color-blue-700: oklch(48.8% .243 264.376); --color-blue-800: oklch(42.4% .199 265.638); --color-blue-900: oklch(37.9% .146 265.522); --color-blue-950: oklch(28.2% .091 267.935); --color-indigo-50: oklch(96.2% .018 272.314); --color-indigo-100: oklch(93% .034 272.788); --color-indigo-200: oklch(87% .065 274.039); --color-indigo-300: oklch(78.5% .115 274.713); --color-indigo-400: oklch(67.3% .182 276.935); --color-indigo-500: oklch(58.5% .233 277.117); --color-indigo-600: oklch(51.1% .262 276.966); --color-indigo-700: oklch(45.7% .24 277.023); --color-indigo-800: oklch(39.8% .195 277.366); --color-indigo-900: oklch(35.9% .144 278.697); --color-indigo-950: oklch(25.7% .09 281.288); --color-violet-50: oklch(96.9% .016 293.756); --color-violet-100: oklch(94.3% .029 294.588); --color-violet-200: oklch(89.4% .057 293.283); --color-violet-300: oklch(81.1% .111 293.571); --color-violet-400: oklch(70.2% .183 293.541); --color-violet-500: oklch(60.6% .25 292.717); --color-violet-600: oklch(54.1% .281 293.009); --color-violet-700: oklch(49.1% .27 292.581); --color-violet-800: oklch(43.2% .232 292.759); --color-violet-900: oklch(38% .189 293.745); --color-violet-950: oklch(28.3% .141 291.089); --color-purple-50: oklch(97.7% .014 308.299); --color-purple-100: oklch(94.6% .033 307.174); --color-purple-200: oklch(90.2% .063 306.703); --color-purple-300: oklch(82.7% .119 306.383); --color-purple-400: oklch(71.4% .203 305.504); --color-purple-500: oklch(62.7% .265 303.9); --color-purple-600: oklch(55.8% .288 302.321); --color-purple-700: oklch(49.6% .265 301.924); --color-purple-800: oklch(43.8% .218 303.724); --color-purple-900: oklch(38.1% .176 304.987); --color-purple-950: oklch(29.1% .149 302.717); --color-fuchsia-50: oklch(97.7% .017 320.058); --color-fuchsia-100: oklch(95.2% .037 318.852); --color-fuchsia-200: oklch(90.3% .076 319.62); --color-fuchsia-300: oklch(83.3% .145 321.434); --color-fuchsia-400: oklch(74% .238 322.16); --color-fuchsia-500: oklch(66.7% .295 322.15); --color-fuchsia-600: oklch(59.1% .293 322.896); --color-fuchsia-700: oklch(51.8% .253 323.949); --color-fuchsia-800: oklch(45.2% .211 324.591); --color-fuchsia-900: oklch(40.1% .17 325.612); --color-fuchsia-950: oklch(29.3% .136 325.661); --color-pink-50: oklch(97.1% .014 343.198); --color-pink-100: oklch(94.8% .028 342.258); --color-pink-200: oklch(89.9% .061 343.231); --color-pink-300: oklch(82.3% .12 346.018); --color-pink-400: oklch(71.8% .202 349.761); --color-pink-500: oklch(65.6% .241 354.308); --color-pink-600: oklch(59.2% .249 .584); --color-pink-700: oklch(52.5% .223 3.958); --color-pink-800: oklch(45.9% .187 3.815); --color-pink-900: oklch(40.8% .153 2.432); --color-pink-950: oklch(28.4% .109 3.907); --color-rose-50: oklch(96.9% .015 12.422); --color-rose-100: oklch(94.1% .03 12.58); --color-rose-200: oklch(89.2% .058 10.001); --color-rose-300: oklch(81% .117 11.638); --color-rose-400: oklch(71.2% .194 13.428); --color-rose-500: oklch(64.5% .246 16.439); --color-rose-600: oklch(58.6% .253 17.585); --color-rose-700: oklch(51.4% .222 16.935); --color-rose-800: oklch(45.5% .188 13.697); --color-rose-900: oklch(41% .159 10.272); --color-rose-950: oklch(27.1% .105 12.094); --color-slate-50: oklch(98.4% .003 247.858); --color-slate-100: oklch(96.8% .007 247.896); --color-slate-200: oklch(92.9% .013 255.508); --color-slate-300: oklch(86.9% .022 252.894); --color-slate-400: oklch(70.4% .04 256.788); --color-slate-500: oklch(55.4% .046 257.417); --color-slate-600: oklch(44.6% .043 257.281); --color-slate-700: oklch(37.2% .044 257.287); --color-slate-800: oklch(27.9% .041 260.031); --color-slate-900: oklch(20.8% .042 265.755); --color-slate-950: oklch(12.9% .042 264.695); --color-gray-50: oklch(98.5% .002 247.839); --color-gray-100: oklch(96.7% .003 264.542); --color-gray-200: oklch(92.8% .006 264.531); --color-gray-300: oklch(87.2% .01 258.338); --color-gray-400: oklch(70.7% .022 261.325); --color-gray-500: oklch(55.1% .027 264.364); --color-gray-600: oklch(44.6% .03 256.802); --color-gray-700: oklch(37.3% .034 259.733); --color-gray-800: oklch(27.8% .033 256.848); --color-gray-900: oklch(21% .034 264.665); --color-gray-950: oklch(13% .028 261.692); --color-zinc-50: oklch(98.5% 0 0); --color-zinc-100: oklch(96.7% .001 286.375); --color-zinc-200: oklch(92% .004 286.32); --color-zinc-300: oklch(87.1% .006 286.286); --color-zinc-400: oklch(70.5% .015 286.067); --color-zinc-500: oklch(55.2% .016 285.938); --color-zinc-600: oklch(44.2% .017 285.786); --color-zinc-700: oklch(37% .013 285.805); --color-zinc-800: oklch(27.4% .006 286.033); --color-zinc-900: oklch(21% .006 285.885); --color-zinc-950: oklch(14.1% .005 285.823); --color-neutral-50: oklch(98.5% 0 0); --color-neutral-100: oklch(97% 0 0); --color-neutral-200: oklch(92.2% 0 0); --color-neutral-300: oklch(87% 0 0); --color-neutral-400: oklch(70.8% 0 0); --color-neutral-500: oklch(55.6% 0 0); --color-neutral-600: oklch(43.9% 0 0); --color-neutral-700: oklch(37.1% 0 0); --color-neutral-800: oklch(26.9% 0 0); --color-neutral-900: oklch(20.5% 0 0); --color-neutral-950: oklch(14.5% 0 0); --color-stone-50: oklch(98.5% .001 106.423); --color-stone-100: oklch(97% .001 106.424); --color-stone-200: oklch(92.3% .003 48.717); --color-stone-300: oklch(86.9% .005 56.366); --color-stone-400: oklch(70.9% .01 56.259); --color-stone-500: oklch(55.3% .013 58.071); --color-stone-600: oklch(44.4% .011 73.639); --color-stone-700: oklch(37.4% .01 67.558); --color-stone-800: oklch(26.8% .007 34.298); --color-stone-900: oklch(21.6% .006 56.043); --color-stone-950: oklch(14.7% .004 49.25); --color-mauve-50: oklch(98.5% 0 0); --color-mauve-100: oklch(96% .003 325.6); --color-mauve-200: oklch(92.2% .005 325.62); --color-mauve-300: oklch(86.5% .012 325.68); --color-mauve-400: oklch(71.1% .019 323.02); --color-mauve-500: oklch(54.2% .034 322.5); --color-mauve-600: oklch(43.5% .029 321.78); --color-mauve-700: oklch(36.4% .029 323.89); --color-mauve-800: oklch(26.3% .024 320.12); --color-mauve-900: oklch(21.2% .019 322.12); --color-mauve-950: oklch(14.5% .008 326); --color-olive-50: oklch(98.8% .003 106.5); --color-olive-100: oklch(96.6% .005 106.5); --color-olive-200: oklch(93% .007 106.5); --color-olive-300: oklch(88% .011 106.6); --color-olive-400: oklch(73.7% .021 106.9); --color-olive-500: oklch(58% .031 107.3); --color-olive-600: oklch(46.6% .025 107.3); --color-olive-700: oklch(39.4% .023 107.4); --color-olive-800: oklch(28.6% .016 107.4); --color-olive-900: oklch(22.8% .013 107.4); --color-olive-950: oklch(15.3% .006 107.1); --color-mist-50: oklch(98.7% .002 197.1); --color-mist-100: oklch(96.3% .002 197.1); --color-mist-200: oklch(92.5% .005 214.3); --color-mist-300: oklch(87.2% .007 219.6); --color-mist-400: oklch(72.3% .014 214.4); --color-mist-500: oklch(56% .021 213.5); --color-mist-600: oklch(45% .017 213.2); --color-mist-700: oklch(37.8% .015 216); --color-mist-800: oklch(27.5% .011 216.9); --color-mist-900: oklch(21.8% .008 223.9); --color-mist-950: oklch(14.8% .004 228.8); --color-taupe-50: oklch(98.6% .002 67.8); --color-taupe-100: oklch(96% .002 17.2); --color-taupe-200: oklch(92.2% .005 34.3); --color-taupe-300: oklch(86.8% .007 39.5); --color-taupe-400: oklch(71.4% .014 41.2); --color-taupe-500: oklch(54.7% .021 43.1); --color-taupe-600: oklch(43.8% .017 39.3); --color-taupe-700: oklch(36.7% .016 35.7); --color-taupe-800: oklch(26.8% .011 36.5); --color-taupe-900: oklch(21.4% .009 43.1); --color-taupe-950: oklch(14.7% .004 49.3); --color-black: #000; --color-white: #fff; --spacing: .25rem; --breakpoint-sm: 40rem; --breakpoint-md: 48rem; --breakpoint-lg: 64rem; --breakpoint-xl: 80rem; --breakpoint-2xl: 96rem; --container-3xs: 16rem; --container-2xs: 18rem; --container-xs: 20rem; --container-sm: 24rem; --container-md: 28rem; --container-lg: 32rem; --container-xl: 36rem; --container-2xl: 42rem; --container-3xl: 48rem; --container-4xl: 56rem; --container-5xl: 64rem; --container-6xl: 72rem; --container-7xl: 80rem; --text-xs: .75rem; --text-xs--line-height: calc(1 / .75); --text-sm: .875rem; --text-sm--line-height: calc(1.25 / .875); --text-base: 1rem; --text-base--line-height: calc(1.5 / 1); --text-lg: 1.125rem; --text-lg--line-height: calc(1.75 / 1.125); --text-xl: 1.25rem; --text-xl--line-height: calc(1.75 / 1.25); --text-2xl: 1.5rem; --text-2xl--line-height: calc(2 / 1.5); --text-3xl: 1.875rem; --text-3xl--line-height: calc(2.25 / 1.875); --text-4xl: 2.25rem; --text-4xl--line-height: calc(2.5 / 2.25); --text-5xl: 3rem; --text-5xl--line-height: 1; --text-6xl: 3.75rem; --text-6xl--line-height: 1; --text-7xl: 4.5rem; --text-7xl--line-height: 1; --text-8xl: 6rem; --text-8xl--line-height: 1; --text-9xl: 8rem; --text-9xl--line-height: 1; --font-weight-thin: 100; --font-weight-extralight: 200; --font-weight-light: 300; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; --font-weight-extrabold: 800; --font-weight-black: 900; --tracking-tighter: -.05em; --tracking-tight: -.025em; --tracking-normal: 0em; --tracking-wide: .025em; --tracking-wider: .05em; --tracking-widest: .1em; --leading-tight: 1.25; --leading-snug: 1.375; --leading-normal: 1.5; --leading-relaxed: 1.625; --leading-loose: 2; --radius-xs: .125rem; --radius-sm: .25rem; --radius-md: .375rem; --radius-lg: .5rem; --radius-xl: .75rem; --radius-2xl: 1rem; --radius-3xl: 1.5rem; --radius-4xl: 2rem; --shadow-2xs: 0 1px #0000000d; --shadow-xs: 0 1px 2px 0 #0000000d; --shadow-sm: 0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a; --shadow-md: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a; --shadow-lg: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a; --shadow-xl: 0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a; --shadow-2xl: 0 25px 50px -12px #00000040; --inset-shadow-2xs: inset 0 1px #0000000d; --inset-shadow-xs: inset 0 1px 1px #0000000d; --inset-shadow-sm: inset 0 2px 4px #0000000d; --drop-shadow-xs: 0 1px 1px #0000000d; --drop-shadow-sm: 0 1px 2px #00000026; --drop-shadow-md: 0 3px 3px #0000001f; --drop-shadow-lg: 0 4px 4px #00000026; --drop-shadow-xl: 0 9px 7px #0000001a; --drop-shadow-2xl: 0 25px 25px #00000026; --text-shadow-2xs: 0px 1px 0px #00000026; --text-shadow-xs: 0px 1px 1px #0003; --text-shadow-sm: 0px 1px 0px #00000013, 0px 1px 1px #00000013, 0px 2px 2px #00000013; --text-shadow-md: 0px 1px 1px #0000001a, 0px 1px 2px #0000001a, 0px 2px 4px #0000001a; --text-shadow-lg: 0px 1px 2px #0000001a, 0px 3px 2px #0000001a, 0px 4px 8px #0000001a; --ease-in: cubic-bezier(.4, 0, 1, 1); --ease-out: cubic-bezier(0, 0, .2, 1); --ease-in-out: cubic-bezier(.4, 0, .2, 1); --animate-spin: spin 1s linear infinite; --animate-ping: ping 1s cubic-bezier(0, 0, .2, 1) infinite; --animate-pulse: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite; --animate-bounce: bounce 1s infinite; @keyframes spin { to { transform: rotate(360deg); } } @keyframes ping { 75%, 100% { transform: scale(2); opacity: 0; } } @keyframes pulse { 50% { opacity: .5; } } @keyframes bounce { 0%, 100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(.8, 0, 1, 1); } 50% { transform: none; animation-timing-function: cubic-bezier(0, 0, .2, 1); } } --blur-xs: 4px; --blur-sm: 8px; --blur-md: 12px; --blur-lg: 16px; --blur-xl: 24px; --blur-2xl: 40px; --blur-3xl: 64px; --perspective-dramatic: 100px; --perspective-near: 300px; --perspective-normal: 500px; --perspective-midrange: 800px; --perspective-distant: 1200px; --aspect-video: 16 / 9; --default-transition-duration: .15s; --default-transition-timing-function: cubic-bezier(.4, 0, .2, 1); --default-font-family: --theme(--font-sans, initial); --default-font-feature-settings: --theme(--font-sans--font-feature-settings, initial); --default-font-variation-settings: --theme(--font-sans--font-variation-settings, initial); --default-mono-font-family: --theme(--font-mono, initial); --default-mono-font-feature-settings: --theme(--font-mono--font-feature-settings, initial); --default-mono-font-variation-settings: --theme(--font-mono--font-variation-settings, initial);}@theme default inline reference{--blur: 8px; --shadow: 0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a; --shadow-inner: inset 0 2px 4px 0 #0000000d; --drop-shadow: 0 1px 2px #0000001a, 0 1px 1px #0000000f; --radius: .25rem; --max-width-prose: 65ch;}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:--theme(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:--theme(--default-font-feature-settings, normal);font-variation-settings:--theme(--default-font-variation-settings, normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:--theme(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:--theme(--default-mono-font-feature-settings, normal);font-variation-settings:--theme(--default-mono-font-variation-settings, normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{@tailwind utilities;}@apply flex w-full justify-center;@apply w-full min-h-screen h-screen;.page{grid-template:"header"4rem"main"1fr"footer"/100%;display:grid}@apply flex items-center gap-4 border-b bg-(--background) px-4 md:px-6;.header{grid-area:header}@apply inline-flex items-center gap-2;@apply h-6 w-6 shrink-0;@apply text-lg font-semibold text-(--foreground);@apply hidden md:flex flex-row items-center gap-5 lg:gap-6;@apply text-(--muted-foreground) transition-colors hover:text-(--foreground) px-0;@apply grid gap-6 text-lg font-medium p-4;@apply text-(--muted-foreground) hover:text-(--foreground) justify-start px-0 text-lg;@apply ml-auto flex items-center gap-2 lg:gap-4;@apply bg-(--background) p-4 py-2 md:p-8 md:py-4;.main{grid-area:main;min-height:0;overflow-y:auto}@apply bg-(--background) text-(--muted-foreground) px-4 py-2 md:px-8 md:py-4;.footer{grid-area:footer}.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
+ .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}
2
2
  /*$vite$:1*/
package/mountain-snow.svg DELETED
@@ -1,4 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2
- <path d="m8 3 4 8 5-5 5 15H2L8 3z"/>
3
- <path d="M4.14 15.08c2.62-1.57 5.24-1.43 7.86.42 2.74 1.94 5.49 2 8.23.19"/>
4
- </svg>
package/r/badge.json DELETED
@@ -1,35 +0,0 @@
1
- {
2
- "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
- "name": "badge",
4
- "type": "registry:component",
5
- "description": "Pihanga badge card component",
6
- "dependencies": [
7
- "@radix-ui/react-slot@^1.2.4",
8
- "class-variance-authority@^0.7.1"
9
- ],
10
- "registryDependencies": [
11
- "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
12
- "badge",
13
- "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-lib-utils.json"
14
- ],
15
- "files": [
16
- {
17
- "path": "cards/badge/badge.component.tsx",
18
- "content": "import * as React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Badge} from \"@/components/ui/badge\";\nimport {cn} from \"@/lib/utils\";\nimport type {BadgeCardProps} from \"./badge.types\";\n\n/**\n * `shad/badge` card component.\n *\n * Renders a shadcn `<Badge>` element with a `label` and an optional `variant`.\n * The variant vocabulary is intentionally identical to the `BadgeColumn.variants`\n * map used by the `shad/data-table` card, so both can be driven from the same\n * source-of-truth value:\n *\n * \"default\" | \"secondary\" | \"destructive\" | \"outline\"\n */\nexport const BadgeComponent = (\n props: PiCardProps<BadgeCardProps>,\n): React.ReactNode => {\n const {label, variant = \"secondary\", className, cardName} = props;\n\n return (\n <Badge\n variant={variant}\n className={cn(className)}\n data-pihanga={cardName}\n >\n {label}\n </Badge>\n );\n};\n",
19
- "type": "registry:component",
20
- "target": "src/cards/badge/badge.component.tsx"
21
- },
22
- {
23
- "path": "cards/badge/badge.types.ts",
24
- "content": "import {createCardDeclaration} from \"@pihanga2/core\";\n\nexport const BADGE_CARD = \"shad/badge\";\n\n/**\n * Badge visual style variants — mirrors the shadcn `Badge` `variant` prop and\n * the `variants` map used in the dataTable `BadgeColumn` type, so the same\n * string values work in both contexts.\n *\n * | Value | Appearance |\n * |-----------------|------------------------------------------|\n * | `\"default\"` | Primary colour, filled |\n * | `\"secondary\"` | Muted/secondary colour, filled (default) |\n * | `\"destructive\"` | Red / error colour, filled |\n * | `\"outline\"` | Transparent background, border only |\n */\nexport type BadgeVariant = \"default\" | \"secondary\" | \"destructive\" | \"outline\";\n\nexport type BadgeCardProps = {\n /** Text content rendered inside the badge */\n label: string;\n\n /**\n * Visual style variant. Matches the shadcn Badge variants and the\n * `BadgeColumn.variants` map in `dataTable.types.ts`.\n * @default \"secondary\"\n */\n variant?: BadgeVariant;\n\n /** Additional Tailwind classes applied to the `<Badge>` element */\n className?: string;\n};\n\n/**\n * Factory function for declaring a `shad/badge` card instance.\n *\n * ```ts\n * import {registerCard} from \"@pihanga2/core\";\n * import {ShadBadge} from \"@/cards/badge\";\n *\n * registerCard(\"myApp/status\", ShadBadge({label: \"Active\", variant: \"default\"}));\n * ```\n */\nexport const ShadBadge = createCardDeclaration<BadgeCardProps>(BADGE_CARD);\n",
25
- "type": "registry:component",
26
- "target": "src/cards/badge/badge.types.ts"
27
- },
28
- {
29
- "path": "cards/badge/index.ts",
30
- "content": "import {registerCardComponent} from \"@pihanga2/core\";\n\nimport {BadgeComponent} from \"./badge.component\";\nimport {BADGE_CARD} from \"./badge.types\";\n\nexport * from \"./badge.types\";\n\nregisterCardComponent({\n name: BADGE_CARD,\n component: BadgeComponent,\n});\n",
31
- "type": "registry:component",
32
- "target": "src/cards/badge/index.ts"
33
- }
34
- ]
35
- }
package/r/box.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
- "name": "box",
4
- "type": "registry:component",
5
- "description": "Pihanga box card component",
6
- "dependencies": [
7
- "@pihanga2/cards@^0.3.15"
8
- ],
9
- "registryDependencies": [
10
- "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json"
11
- ],
12
- "files": [
13
- {
14
- "path": "cards/box/box.component.tsx",
15
- "content": "import * as React from \"react\";\n\nimport {Card, type PiCardProps} from \"@pihanga2/core\";\nimport type {BoxProps} from \"@pihanga2/cards\";\n\nexport const BoxComponent = (props: PiCardProps<BoxProps>): React.ReactNode => {\n const {content, className, style, cardName} = props;\n\n let sy: Record<string, string | number> = {};\n if (props.height) sy.height = `${props.height}px`;\n if (props.width) sy.height = `${props.width}px`;\n\n if (props.marginTop) sy[\"margin-top\"] = `${props.marginTop}px`;\n if (props.marginBottom) sy[\"margin-bottom\"] = `${props.marginBottom}px`;\n if (props.marginLeft) sy[\"margin-ledt\"] = `${props.marginLeft}px`;\n if (props.marginRight) sy[\"margin-right\"] = `${props.marginRight}px`;\n\n if (props.paddingTop) sy[\"padding-top\"] = `${props.paddingTop}px`;\n if (props.paddingBottom) sy[\"padding-bottom\"] = `${props.paddingBottom}px`;\n if (props.paddingLeft) sy[\"padding-ledt\"] = `${props.paddingLeft}px`;\n if (props.paddingRight) sy[\"padding-right\"] = `${props.paddingRight}px`;\n\n sy = {\n ...(style?.shad as Record<string, string | number> | undefined),\n };\n\n function renderContent() {\n if (!content) return null;\n return content.map((cn, i) => (\n <Card cardName={cn} parentCard={cardName} key={i} />\n ));\n }\n\n return (\n <div className={className} style={sy} data-pihanga={cardName}>\n {renderContent()}\n {props.children}\n </div>\n );\n};\n",
16
- "type": "registry:component",
17
- "target": "src/cards/box/box.component.tsx"
18
- },
19
- {
20
- "path": "cards/box/index.ts",
21
- "content": "import {createCardDeclaration, registerCardComponent} from \"@pihanga2/core\";\n\nimport {BoxComponent} from \"./box.component\";\nimport type {BoxProps} from \"@pihanga2/cards\";\n\nexport const BOX_CARD = \"shad/box\";\nexport const Box = createCardDeclaration<BoxProps>(BOX_CARD);\n\nregisterCardComponent({\n name: BOX_CARD,\n component: BoxComponent,\n});\n",
22
- "type": "registry:component",
23
- "target": "src/cards/box/index.ts"
24
- }
25
- ]
26
- }
package/r/button.json DELETED
@@ -1,39 +0,0 @@
1
- {
2
- "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
- "name": "button",
4
- "type": "registry:component",
5
- "description": "Pihanga button card component",
6
- "dependencies": [
7
- "@radix-ui/react-tooltip@^1.2.8",
8
- "class-variance-authority@^0.7.1",
9
- "lucide-react@^0.513.0",
10
- "radix-ui@^1.4.3"
11
- ],
12
- "registryDependencies": [
13
- "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
14
- "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-ui-extras.json",
15
- "tooltip",
16
- "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-cards-icons.json",
17
- "https://ivcap-works.github.io/pihanga-shadcn/r/dropDownMenu.json"
18
- ],
19
- "files": [
20
- {
21
- "path": "cards/button/button.component.tsx",
22
- "content": "import React from \"react\";\nimport {Card, type PiCardProps} from \"@pihanga2/core\";\n\nimport {Button, LinkButton} from \"@/components/ui/button\";\nimport {Tooltip, TooltipContent, TooltipTrigger} from \"@/components/ui/tooltip\";\nimport {getIcon} from \"@/cards/icons\";\nimport {useDropdownOpen} from \"@/cards/dropDownMenu/dropdown-context\";\n\nimport type {PiButtonEvents, PiButtonProps} from \"./button.types\";\n\nfunction resolveIconByName(name?: string): React.ReactNode {\n if (!name) return null;\n return getIcon(name);\n}\n\nexport const ButtonComponent = (\n props: PiCardProps<PiButtonProps, PiButtonEvents>,\n): React.ReactNode => {\n const {\n opts,\n ariaLabel,\n label,\n iconLabel,\n contentCard: content,\n href,\n target,\n tooltip,\n tooltipCard,\n tooltipMode,\n tooltipPlacement,\n className,\n id,\n onClicked,\n cardName,\n _cls,\n active,\n focused,\n disabled,\n loading,\n isPending,\n } = props;\n\n // Check if this button is inside an open dropdown menu\n const isInsideOpenDropdown = useDropdownOpen();\n\n const beforeIcon = resolveIconByName(opts?.beforeIcon);\n const afterIcon = resolveIconByName(opts?.afterIcon);\n\n // Determine base content: iconLabel takes precedence, then contentCard, then label\n const baseContent = iconLabel ? (\n resolveIconByName(iconLabel)\n ) : content ? (\n <Card cardName={content} parentCard={cardName} />\n ) : (\n label\n );\n\n // Render icons as children following shadcn/ui pattern\n const children = (\n <>\n {beforeIcon}\n {baseContent}\n {afterIcon}\n </>\n );\n\n const common = {\n active,\n focused,\n isMenu: opts?.isMenu,\n truncate: opts?.truncate,\n variant: opts?.variant,\n size: opts?.size,\n\n disabled,\n loading,\n isPending,\n loadingClassName: opts?.loadingClassName,\n\n className: `${_cls(\"root\")} ${className || \"\"}`.trim(),\n };\n\n const handleClick = () => {\n onClicked({id});\n };\n\n const renderButton = () => {\n if (href) {\n return (\n <LinkButton\n {...common}\n href={href}\n target={target}\n data-pihanga={cardName}\n label={ariaLabel ?? label}\n onClick={handleClick}\n >\n {children}\n </LinkButton>\n );\n }\n\n return (\n <Button\n {...common}\n data-pihanga={cardName}\n label={ariaLabel ?? label}\n onClick={handleClick}\n >\n {children}\n </Button>\n );\n };\n\n if (!tooltip && !tooltipCard) return renderButton();\n\n // Determine tooltip open state based on mode.\n // If the button is inside an open dropdown, force the tooltip closed\n // to avoid UI conflicts (dropdown menu should take precedence).\n const tooltipOpen = isInsideOpenDropdown\n ? false\n : tooltipMode === \"open\"\n ? true\n : tooltipMode === \"closed\"\n ? false\n : undefined; // 'auto' or undefined = uncontrolled\n\n // Render tooltip content: use tooltipCard if provided, otherwise use tooltip string\n const tooltipContent = tooltipCard ? (\n <Card cardName={tooltipCard} parentCard={cardName} />\n ) : (\n <p data-pihanga={`${cardName}-tooltip`}>{tooltip}</p>\n );\n\n return (\n <Tooltip open={tooltipOpen}>\n <TooltipTrigger asChild>{renderButton()}</TooltipTrigger>\n <TooltipContent side={tooltipPlacement}>{tooltipContent}</TooltipContent>\n </Tooltip>\n );\n};\n",
23
- "type": "registry:component",
24
- "target": "src/cards/button/button.component.tsx"
25
- },
26
- {
27
- "path": "cards/button/button.types.ts",
28
- "content": "import {\n createCardDeclaration,\n createOnAction,\n PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_BUTTON_CARD = \"pi/button\";\n\nexport const Button = createCardDeclaration<PiButtonProps, PiButtonEvents>(\n PI_BUTTON_CARD,\n);\n\nexport const PI_BUTTON_ACTION = registerActions(PI_BUTTON_CARD, [\"clicked\"]);\n\nexport const onPiButtonClicked = createOnAction<PiButtonClickedEvent>(\n PI_BUTTON_ACTION.CLICKED,\n);\n\n/**\n * Declarative \"opts\" subset based on `src/registry/ui/button.tsx`.\n *\n * Notes:\n * - Any icon is referenced by name and resolved via `src/pihanga/icons.ts`.\n * - `children` are provided via `label` (simple) or `content` (card ref).\n */\nexport type PiButtonOpts = {\n /**\n * Visual style variant of the button.\n * Determines the button's appearance (colors, borders, etc.).\n */\n variant?:\n | \"default\"\n | \"destructive\"\n | \"outline\"\n | \"secondary\"\n | \"ghost\"\n | \"ghost2\"\n | \"ghost3\"\n | \"ghostActive\"\n | \"brand\"\n | \"nav\"\n | \"navAction\"\n | \"menuAction\"\n | \"blockAction\"\n | \"blockActionSecondary\"\n | \"primaryOutline\"\n | \"radio\"\n | \"none\";\n\n /**\n * Size of the button.\n * Controls padding, font size, and overall dimensions.\n */\n size?:\n | \"default\"\n | \"xs\"\n | \"md\"\n | \"lg\"\n | \"icon\"\n | \"iconSm\"\n | \"navAction\"\n | \"menuAction\"\n | \"blockAction\"\n | \"none\";\n\n /** Truncate button content with ellipsis if it overflows. */\n truncate?: boolean;\n\n /** If true, button is rendered as a menu trigger button. */\n isMenu?: boolean;\n\n /** Custom CSS class to apply to the loading spinner/indicator. */\n loadingClassName?: string;\n\n /** Icon to display before the button content. Set 'size' to 'icon' if ONLY show icon */\n beforeIcon?: string;\n\n /** Icon to display after the button content */\n afterIcon?: string;\n};\n\nexport type PiButtonProps = {\n id?: string; // optional 'id' to be added to events\n\n /**\n * Optional explicit aria-label.\n *\n * Useful for icon-only / letter-only buttons where the visible content\n * shouldn't be used as the accessible name.\n */\n ariaLabel?: string;\n\n /**\n * Declarative options; maps closely to `@/components/ui/button`.\n */\n opts?: PiButtonOpts;\n\n /** Simple label; used as children and aria-label fallback. */\n label?: string;\n\n /**\n * Icon name to use as the main button content (instead of text label).\n * Resolved via `src/pihanga/icons.ts`.\n * Takes precedence over `label` and `contentCard`.\n */\n iconLabel?: string;\n\n /**\n * If set, renders this card as the content instead of `label`.\n * (Useful for rich content.)\n */\n contentCard?: PiCardRef;\n\n /** When provided, button will render as an anchor. */\n href?: string;\n target?: string;\n\n tooltip?: string;\n\n /**\n * If set, renders this card as the tooltip content instead of `tooltip`.\n * (Useful for rich tooltip content.)\n */\n tooltipCard?: PiCardRef;\n\n /**\n * Controls tooltip visibility mode.\n * - 'auto' (default): Normal hover behavior\n * - 'open': Force tooltip to be visible\n * - 'closed': Force tooltip to be hidden\n */\n tooltipMode?: \"auto\" | \"open\" | \"closed\";\n\n /**\n * Controls tooltip placement/position.\n * - 'top': Tooltip appears above the button (default)\n * - 'right': Tooltip appears to the right of the button\n * - 'bottom': Tooltip appears below the button\n * - 'left': Tooltip appears to the left of the button\n */\n tooltipPlacement?: \"top\" | \"right\" | \"bottom\" | \"left\";\n\n /** Indicates whether the button is in an active/selected state. */\n active?: boolean;\n\n /** Indicates whether the button has focus state styling applied. */\n focused?: boolean;\n\n /** If true, disables the button and prevents interaction. */\n disabled?: boolean;\n\n /** If true, shows loading state and typically disables interaction. */\n loading?: boolean;\n\n /** If true, indicates an async operation is pending (similar to loading but distinct). */\n isPending?: boolean;\n\n className?: string;\n};\n\nexport type PiButtonClickedEvent = {\n id?: string;\n};\n\nexport type PiButtonEvents = {\n onClicked: PiButtonClickedEvent;\n};\n",
29
- "type": "registry:component",
30
- "target": "src/cards/button/button.types.ts"
31
- },
32
- {
33
- "path": "cards/button/index.ts",
34
- "content": "import {actionTypesToEvents, registerCardComponent} from \"@pihanga2/core\";\n\nimport {ButtonComponent} from \"./button.component\";\nimport {PI_BUTTON_ACTION, PI_BUTTON_CARD} from \"./button.types\";\n\nexport * from \"./button.types\";\n\n// Optional convenience alias (mirrors older pattern like SdDropDownMenu)\n// export const SdButton = createCardDeclaration<PiButtonProps, PiButtonEvents>(\n// PI_BUTTON_CARD,\n// );\n\nregisterCardComponent({\n name: PI_BUTTON_CARD,\n component: ButtonComponent,\n events: actionTypesToEvents(PI_BUTTON_ACTION),\n});\n",
35
- "type": "registry:component",
36
- "target": "src/cards/button/index.ts"
37
- }
38
- ]
39
- }
package/r/checkbox.json DELETED
@@ -1,31 +0,0 @@
1
- {
2
- "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
- "name": "checkbox",
4
- "type": "registry:component",
5
- "description": "Pihanga checkbox card component",
6
- "dependencies": [],
7
- "registryDependencies": [
8
- "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
9
- "https://ivcap-works.github.io/pihanga-shadcn/r/form.json"
10
- ],
11
- "files": [
12
- {
13
- "path": "cards/checkbox/checkbox.component.tsx",
14
- "content": "import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiCheckboxEvents, PiCheckboxProps} from \"./checkbox.types\";\n\nexport const CheckboxComponent = (\n props: PiCardProps<PiCheckboxProps, PiCheckboxEvents>,\n): React.ReactNode => {\n const {\n name,\n checked: propChecked = false,\n disabled,\n label,\n cardName,\n onChanged,\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 const checked = useFormData\n ? Boolean(form.formData[name!] ?? false)\n : propChecked;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newChecked = e.target.checked;\n if (useFormData) {\n form.handleChange(name!, newChecked);\n } else {\n onChanged({name, checked: newChecked});\n }\n }\n\n // Use the id injected by pi/field; fall back to a local id when standalone.\n const selfId = `${cardName}-${name ?? \"checkbox\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div data-pihanga={cardName} className=\"flex items-center gap-2\">\n <input\n id={fieldId}\n type=\"checkbox\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n className=\"h-4 w-4 rounded border-input accent-primary disabled:cursor-not-allowed disabled:opacity-50\"\n />\n {label && (\n <label\n htmlFor={fieldId}\n className=\"text-sm leading-none cursor-pointer select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n </label>\n )}\n </div>\n );\n};\n",
15
- "type": "registry:component",
16
- "target": "src/cards/checkbox/checkbox.component.tsx"
17
- },
18
- {
19
- "path": "cards/checkbox/checkbox.types.ts",
20
- "content": "import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_CHECKBOX_CARD = \"pi/checkbox\";\n\nexport const Checkbox = createCardDeclaration<\n PiCheckboxProps,\n PiCheckboxEvents\n>(PI_CHECKBOX_CARD);\n\nexport const PI_CHECKBOX_ACTION = registerActions(PI_CHECKBOX_CARD, [\n \"changed\",\n]);\n\nexport const onPiCheckboxChanged = createOnAction<PiCheckboxChangedEvent>(\n PI_CHECKBOX_ACTION.CHANGED,\n);\n\nexport type PiCheckboxProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its checked state from form data and\n * writes back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled checked state used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n checked?: boolean;\n\n /** When true, the checkbox is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered next to the checkbox.\n * The label is automatically associated with the input via `htmlFor`.\n */\n label?: string;\n};\n\nexport type PiCheckboxChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New checked state after the change. */\n checked: boolean;\n};\n\nexport type PiCheckboxEvents = {\n onChanged: PiCheckboxChangedEvent;\n};\n",
21
- "type": "registry:component",
22
- "target": "src/cards/checkbox/checkbox.types.ts"
23
- },
24
- {
25
- "path": "cards/checkbox/index.ts",
26
- "content": "import {actionTypesToEvents, registerCardComponent} from \"@pihanga2/core\";\n\nimport {CheckboxComponent} from \"./checkbox.component\";\nimport {PI_CHECKBOX_ACTION, PI_CHECKBOX_CARD} from \"./checkbox.types\";\n\nexport * from \"./checkbox.types\";\n\nregisterCardComponent({\n name: PI_CHECKBOX_CARD,\n component: CheckboxComponent,\n events: actionTypesToEvents(PI_CHECKBOX_ACTION),\n});\n",
27
- "type": "registry:component",
28
- "target": "src/cards/checkbox/index.ts"
29
- }
30
- ]
31
- }