@pihanga2/shadcn 0.2.17 → 0.2.19
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.
- package/README.md +6 -1
- package/cards/button/button.types.d.ts +2 -2
- package/cards/checkbox/checkbox.types.d.ts +2 -2
- package/cards/codeMirror/codeMirror.types.d.ts +1 -1
- package/cards/collapsibleCard/collapsibleCard.types.d.ts +1 -1
- package/cards/dataTable/dataTable.types.d.ts +5 -5
- package/cards/dialog/dialog.types.d.ts +3 -3
- package/cards/drawer/drawer.types.d.ts +3 -3
- package/cards/dropDownMenu/drop-down.types.d.ts +1 -1
- package/cards/emptyCard/emptyCard.component.js +25 -0
- package/cards/emptyCard/emptyCard.component.js.map +1 -0
- package/cards/emptyCard/emptyCard.types.js +7 -0
- package/cards/emptyCard/emptyCard.types.js.map +1 -0
- package/cards/emptyCard/index.js +12 -0
- package/cards/emptyCard/index.js.map +1 -0
- package/cards/fileDrop/fileDrop.types.d.ts +2 -2
- package/cards/form/form.types.d.ts +2 -2
- package/cards/graphin/graphin.types.d.ts +9 -9
- package/cards/input/input.component.js +28 -23
- package/cards/input/input.component.js.map +1 -1
- package/cards/input/input.types.d.ts +10 -4
- package/cards/input/input.types.js.map +1 -1
- package/cards/jsonViewer/jsonViewer.types.d.ts +2 -2
- package/cards/keyboardOverlay/keyboardOverlay.component.js +1 -0
- package/cards/keyboardOverlay/keyboardOverlay.component.js.map +1 -1
- package/cards/keyboardOverlay/keyboardOverlay.types.d.ts +1 -1
- package/cards/list/list.types.d.ts +1 -1
- package/cards/menu/menu.types.d.ts +1 -1
- package/cards/modeToggle/mode-toggle.types.d.ts +1 -1
- package/cards/navbarSearch/navbarSearch.type.d.ts +3 -3
- package/cards/observable/index.d.ts +1 -0
- package/cards/observable/index.js +13 -0
- package/cards/observable/index.js.map +1 -0
- package/cards/observable/observable.component.d.ts +4 -0
- package/cards/observable/observable.component.js +74 -0
- package/cards/observable/observable.component.js.map +1 -0
- package/cards/observable/observable.types.d.ts +253 -0
- package/cards/observable/observable.types.js +21 -0
- package/cards/observable/observable.types.js.map +1 -0
- package/cards/pageWithNavbar/pageWithNavbar.type.d.ts +1 -1
- package/cards/pageWithNavbarMeta/pageWithNavbarMeta.types.d.ts +1 -1
- package/cards/pasteTarget/pasteTarget.types.d.ts +2 -2
- package/cards/resizableColumns/index.js +12 -0
- package/cards/resizableColumns/index.js.map +1 -0
- package/cards/resizableColumns/resizableColumns.component.js +105 -0
- package/cards/resizableColumns/resizableColumns.component.js.map +1 -0
- package/cards/resizableColumns/resizableColumns.css +1 -0
- package/cards/resizableColumns/resizableColumns.types.js +7 -0
- package/cards/resizableColumns/resizableColumns.types.js.map +1 -0
- package/cards/resizableGrid/index.js +12 -0
- package/cards/resizableGrid/index.js.map +1 -0
- package/cards/resizableGrid/resizableGrid.component.js +166 -0
- package/cards/resizableGrid/resizableGrid.component.js.map +1 -0
- package/cards/resizableGrid/resizableGrid.css +1 -0
- package/cards/resizableGrid/resizableGrid.types.js +7 -0
- package/cards/resizableGrid/resizableGrid.types.js.map +1 -0
- package/cards/scrollbarWithAnnotations/scrollbarWithAnnotations.types.d.ts +2 -2
- package/cards/select/select.types.d.ts +6 -6
- package/cards/sheetCard/sheetCard.types.d.ts +3 -3
- package/cards/slider/slider.types.d.ts +4 -4
- package/cards/stack/stack.component.js +51 -38
- package/cards/stack/stack.component.js.map +1 -1
- package/cards/stepper/stepper.types.d.ts +1 -1
- package/cards/switch/switch.types.d.ts +2 -2
- package/cards/tabs/tabs.types.d.ts +1 -1
- package/cards/textArea/index.d.ts +1 -0
- package/cards/textArea/index.js +13 -0
- package/cards/textArea/index.js.map +1 -0
- package/cards/textArea/textArea.component.d.ts +4 -0
- package/cards/textArea/textArea.component.js +83 -0
- package/cards/textArea/textArea.component.js.map +1 -0
- package/cards/textArea/textArea.types.d.ts +147 -0
- package/cards/textArea/textArea.types.js +7 -0
- package/cards/textArea/textArea.types.js.map +1 -0
- package/cards/textField/textField.types.d.ts +2 -2
- package/cards/toast/toast.types.d.ts +3 -3
- package/cards/toggleGroup/toggleGroup.types.d.ts +2 -2
- package/components/ui/empty.js +40 -0
- package/components/ui/empty.js.map +1 -0
- package/components/ui/input.js +11 -11
- package/components/ui/input.js.map +1 -1
- package/components/ui/textarea.js +15 -0
- package/components/ui/textarea.js.map +1 -0
- package/package.json +28 -2
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/utils.js";
|
|
2
|
+
import { useFormContext as t } from "../form/form.context.js";
|
|
3
|
+
import { Textarea as n } from "../../components/ui/textarea.js";
|
|
4
|
+
import { useEffect as r, useRef as i, useState as ee } from "react";
|
|
5
|
+
import "@pihanga2/core";
|
|
6
|
+
import { jsx as a } from "react/jsx-runtime";
|
|
7
|
+
//#region src/cards/textArea/textArea.component.tsx
|
|
8
|
+
function o(e) {
|
|
9
|
+
if (e !== void 0) return typeof e == "number" ? `${e}px` : e;
|
|
10
|
+
}
|
|
11
|
+
var s = (s) => {
|
|
12
|
+
let { name: c, value: l = "", placeholder: u, disabled: d, readOnly: f, rows: p = 4, cols: m, fieldSizing: h = "fixed", resize: g, minHeight: _, maxHeight: v, width: y, height: b, maxWidth: x, dir: S, writingMode: C, submitOnEnter: w, selfManaged: T = !1, debounceMs: E = 0, className: D, style: O, autoFocus: k, cardName: A, onChanged: j, onSubmitted: M } = s, N = i(null);
|
|
13
|
+
r(() => {
|
|
14
|
+
k && N.current?.focus();
|
|
15
|
+
}, []);
|
|
16
|
+
let P = s.id, F = !!s.invalid, I = t(), L = I.isInForm && !!c, R = L ? I.formData[c] ?? "" : l, z = T && !L, [B, V] = ee(R), H = i(null), U = i(R);
|
|
17
|
+
r(() => {
|
|
18
|
+
z && V(R);
|
|
19
|
+
}, [R, z]), r(() => () => {
|
|
20
|
+
H.current != null && clearTimeout(H.current);
|
|
21
|
+
}, []);
|
|
22
|
+
let W = z ? B : R;
|
|
23
|
+
function G(e) {
|
|
24
|
+
L ? I.handleChange(c, e) : j({
|
|
25
|
+
name: c,
|
|
26
|
+
value: e
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function K(e) {
|
|
30
|
+
let t = e.target.value;
|
|
31
|
+
if (!z) {
|
|
32
|
+
G(t);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
V(t), U.current = t, E > 0 && (H.current != null && clearTimeout(H.current), H.current = setTimeout(() => {
|
|
36
|
+
H.current = null, G(U.current);
|
|
37
|
+
}, E));
|
|
38
|
+
}
|
|
39
|
+
function q() {
|
|
40
|
+
z && (H.current != null && (clearTimeout(H.current), H.current = null), G(U.current));
|
|
41
|
+
}
|
|
42
|
+
function J(e) {
|
|
43
|
+
if (w && e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
let t = e.currentTarget.value;
|
|
46
|
+
z && H.current != null && (clearTimeout(H.current), H.current = null, G(t)), M({
|
|
47
|
+
name: c,
|
|
48
|
+
value: t
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let Y = g ?? (h === "content" ? "none" : "vertical"), X = Y === "none" ? "resize-none" : Y === "vertical" ? "resize-y" : Y === "horizontal" ? "resize-x" : "resize", Z = h === "content" ? "field-sizing-content" : "field-sizing-fixed", Q = {
|
|
53
|
+
minHeight: o(_),
|
|
54
|
+
maxHeight: o(v),
|
|
55
|
+
width: o(y),
|
|
56
|
+
height: o(b),
|
|
57
|
+
maxWidth: o(x),
|
|
58
|
+
writingMode: C,
|
|
59
|
+
...O
|
|
60
|
+
}, $ = `${A}-${c ?? "field"}`;
|
|
61
|
+
return /* @__PURE__ */ a(n, {
|
|
62
|
+
ref: N,
|
|
63
|
+
id: P ?? $,
|
|
64
|
+
value: W,
|
|
65
|
+
onChange: K,
|
|
66
|
+
onBlur: q,
|
|
67
|
+
onKeyDown: J,
|
|
68
|
+
placeholder: u,
|
|
69
|
+
disabled: d,
|
|
70
|
+
readOnly: f,
|
|
71
|
+
rows: h === "fixed" ? p : void 0,
|
|
72
|
+
cols: h === "fixed" ? m : void 0,
|
|
73
|
+
dir: S,
|
|
74
|
+
"aria-invalid": F || void 0,
|
|
75
|
+
"data-pihanga": A,
|
|
76
|
+
className: e(Z, X, D),
|
|
77
|
+
style: Q
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { s as TextAreaComponent };
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=textArea.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textArea.component.js","names":[],"sources":["../../../src/cards/textArea/textArea.component.tsx"],"sourcesContent":["import React, {useEffect, useRef, useState} from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Textarea} from \"@/components/ui/textarea\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport {cn} from \"@/lib/utils\";\nimport type {\n CssLength,\n PiTextAreaEvents,\n PiTextAreaProps,\n} from \"./textArea.types\";\n\nfunction toCssLength(v: CssLength | undefined): string | undefined {\n if (v === undefined) return undefined;\n return typeof v === \"number\" ? `${v}px` : v;\n}\n\nexport const TextAreaComponent = (\n props: PiCardProps<PiTextAreaProps, PiTextAreaEvents>,\n): React.ReactNode => {\n const {\n name,\n value: propValue = \"\",\n placeholder,\n disabled,\n readOnly,\n rows = 4,\n cols,\n fieldSizing = \"fixed\",\n resize,\n minHeight,\n maxHeight,\n width,\n height,\n maxWidth,\n dir,\n writingMode,\n submitOnEnter,\n selfManaged = false,\n debounceMs = 0,\n className,\n style,\n autoFocus,\n cardName,\n onChanged,\n onSubmitted,\n } = props;\n\n // Focus the textarea once, the first time it is mounted/shown (e.g. when a\n // dialog or drawer opens). Intentionally an empty dependency array — this\n // must not re-fire on subsequent re-renders.\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n useEffect(() => {\n if (autoFocus) textareaRef.current?.focus();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // `id` may be injected by a parent pi/field card via Pihanga's extra-prop\n // forwarding. Not part of the official type so read 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. When inside a\n // form, the form itself is the source of truth and buffering mechanism\n // (see pi/input, pi/text-field, etc.) — every keystroke writes straight to\n // form.formData via handleChange, and `selfManaged`/`debounceMs` are\n // ignored: there's no separate \"commit\" step to defer since the form's own\n // submit action is that commit point.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n const canonicalValue = useFormData\n ? ((form.formData[name!] as string | undefined) ?? \"\")\n : propValue;\n\n // Self-managed buffering only applies in standalone mode.\n const applySelfManaged = selfManaged && !useFormData;\n\n // ---------------------------------------------------------------------\n // Self-managed mode (standalone only): keep an internal, always-up-to-date\n // text buffer so typing never lags, but only dispatch the outgoing\n // onChanged event on blur (and, optionally, after a trailing debounce\n // window) — not on every keystroke.\n // ---------------------------------------------------------------------\n const [localValue, setLocalValue] = useState(canonicalValue);\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingValue = useRef<string>(canonicalValue);\n\n // Keep the local buffer in sync if the canonical value changes from\n // outside (e.g. a reset) while not actively editing.\n useEffect(() => {\n if (applySelfManaged) setLocalValue(canonicalValue);\n }, [canonicalValue, applySelfManaged]);\n\n useEffect(() => {\n return () => {\n if (debounceTimer.current != null) clearTimeout(debounceTimer.current);\n };\n }, []);\n\n const value = applySelfManaged ? localValue : canonicalValue;\n\n function commitChange(newValue: string) {\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n onChanged({name, value: newValue});\n }\n }\n\n function handleChange(e: React.ChangeEvent<HTMLTextAreaElement>) {\n const newValue = e.target.value;\n\n if (!applySelfManaged) {\n // Inside a form, or selfManaged not requested: commit on every\n // keystroke, matching pi/input's default (non-onCommitted) behaviour.\n commitChange(newValue);\n return;\n }\n\n // Self-managed (standalone): update the visible text immediately, defer\n // the outgoing event.\n setLocalValue(newValue);\n pendingValue.current = newValue;\n\n if (debounceMs > 0) {\n if (debounceTimer.current != null) clearTimeout(debounceTimer.current);\n debounceTimer.current = setTimeout(() => {\n debounceTimer.current = null;\n commitChange(pendingValue.current);\n }, debounceMs);\n }\n }\n\n function handleBlur() {\n if (!applySelfManaged) return;\n if (debounceTimer.current != null) {\n clearTimeout(debounceTimer.current);\n debounceTimer.current = null;\n }\n commitChange(pendingValue.current);\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {\n if (\n submitOnEnter &&\n e.key === \"Enter\" &&\n !e.shiftKey &&\n !e.ctrlKey &&\n !e.metaKey &&\n !e.altKey\n ) {\n e.preventDefault();\n const currentValue = e.currentTarget.value;\n if (applySelfManaged && debounceTimer.current != null) {\n clearTimeout(debounceTimer.current);\n debounceTimer.current = null;\n commitChange(currentValue);\n }\n onSubmitted({name, value: currentValue});\n }\n }\n\n // Default resize behaviour: content-sizing boxes shouldn't be manually\n // resizable (dragging writes an inline width/height that permanently\n // defeats field-sizing: content).\n const resolvedResize =\n resize ?? (fieldSizing === \"content\" ? \"none\" : \"vertical\");\n\n const resizeClass =\n resolvedResize === \"none\"\n ? \"resize-none\"\n : resolvedResize === \"vertical\"\n ? \"resize-y\"\n : resolvedResize === \"horizontal\"\n ? \"resize-x\"\n : \"resize\";\n\n // `field-sizing` is expressed as a Tailwind utility class (shipped by\n // Tailwind v4) rather than an inline style — this is both more idiomatic\n // for this codebase (the base Textarea already defaults to\n // `field-sizing-content`) and avoids relying on very new CSS properties\n // being present in every CSSStyleDeclaration IDL implementation.\n const fieldSizingClass =\n fieldSizing === \"content\" ? \"field-sizing-content\" : \"field-sizing-fixed\";\n\n const inlineStyle: React.CSSProperties = {\n minHeight: toCssLength(minHeight),\n maxHeight: toCssLength(maxHeight),\n width: toCssLength(width),\n height: toCssLength(height),\n maxWidth: toCssLength(maxWidth),\n writingMode,\n ...style,\n };\n\n // Use the id injected by pi/field (for label↔control linking); fall back\n // to a locally-generated id when used standalone.\n const selfId = `${cardName}-${name ?? \"field\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <Textarea\n ref={textareaRef}\n id={fieldId}\n value={value}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={readOnly}\n rows={fieldSizing === \"fixed\" ? rows : undefined}\n cols={fieldSizing === \"fixed\" ? cols : undefined}\n dir={dir}\n aria-invalid={invalid || undefined}\n data-pihanga={cardName}\n className={cn(fieldSizingClass, resizeClass, className)}\n style={inlineStyle}\n />\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
export declare const PI_TEXT_AREA_CARD = "pi/text-area";
|
|
3
|
+
export declare const TextArea: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<PiTextAreaProps, S, PiTextAreaEvents>) => import('@pihanga2/core').PiCardDef;
|
|
4
|
+
export declare const PI_TEXT_AREA_ACTION: {
|
|
5
|
+
CHANGED: string;
|
|
6
|
+
SUBMITTED: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const onTextAreaChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
9
|
+
cardID: string;
|
|
10
|
+
} & PiTextAreaChangedEvent>) => void;
|
|
11
|
+
export declare const onTextAreaSubmitted: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
12
|
+
cardID: string;
|
|
13
|
+
} & PiTextAreaSubmittedEvent>) => void;
|
|
14
|
+
/** A CSS length. Numbers are treated as pixels, strings are used verbatim. */
|
|
15
|
+
export type CssLength = number | string;
|
|
16
|
+
/**
|
|
17
|
+
* How the textarea sizes itself:
|
|
18
|
+
* - "fixed" (default) — plain `<textarea>` behaviour. Size is governed by
|
|
19
|
+
* `rows`/`cols` (and any explicit `width`/`height`); the user
|
|
20
|
+
* may resize it per the `resize` prop. Never grows with content.
|
|
21
|
+
* - "content" — uses the CSS `field-sizing: content` behaviour: the box
|
|
22
|
+
* grows/shrinks to fit its content, clamped by any
|
|
23
|
+
* `minHeight`/`maxHeight`/`width`/`height`/`maxWidth` you set.
|
|
24
|
+
* `rows`/`cols` are ignored by the browser once this is active.
|
|
25
|
+
*/
|
|
26
|
+
export type PiTextAreaFieldSizing = "fixed" | "content";
|
|
27
|
+
export type PiTextAreaResize = "none" | "vertical" | "horizontal" | "both";
|
|
28
|
+
export type PiTextAreaProps = {
|
|
29
|
+
/**
|
|
30
|
+
* Field name used to bind to FormContext when inside a pi/form card.
|
|
31
|
+
* When provided the component reads its value from form state and writes
|
|
32
|
+
* back via form.handleChange.
|
|
33
|
+
*/
|
|
34
|
+
name?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Controlled value used in standalone mode (outside a Form).
|
|
37
|
+
* Ignored when `name` is set and the component is inside a pi/form.
|
|
38
|
+
*/
|
|
39
|
+
value?: string;
|
|
40
|
+
/** Placeholder text shown when the box is empty. May contain `\n`. */
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
/** When true, the textarea is disabled and non-interactive. */
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
/** When true, the textarea's value cannot be edited by the user. */
|
|
45
|
+
readOnly?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Number of visible text lines. Only meaningful when `fieldSizing` is
|
|
48
|
+
* `"fixed"` — browsers ignore `rows`/`cols` once `field-sizing: content`
|
|
49
|
+
* is active. Default: `4`.
|
|
50
|
+
*/
|
|
51
|
+
rows?: number;
|
|
52
|
+
/** Number of visible character columns. See `rows` for caveats. */
|
|
53
|
+
cols?: number;
|
|
54
|
+
/** See `PiTextAreaFieldSizing`. Default: `"fixed"`. */
|
|
55
|
+
fieldSizing?: PiTextAreaFieldSizing;
|
|
56
|
+
/**
|
|
57
|
+
* CSS `resize` behaviour — whether/how the user can drag-resize the box.
|
|
58
|
+
* Default: `"vertical"` when `fieldSizing` is `"fixed"`, `"none"` when
|
|
59
|
+
* `fieldSizing` is `"content"` (dragging would otherwise permanently
|
|
60
|
+
* defeat the content-based sizing by writing an inline width/height).
|
|
61
|
+
*/
|
|
62
|
+
resize?: PiTextAreaResize;
|
|
63
|
+
/** Minimum height. Accepts CSS units like `"2lh"`, `"4rem"`, or a number of px. */
|
|
64
|
+
minHeight?: CssLength;
|
|
65
|
+
/** Maximum height. Once reached, content scrolls instead of growing further. */
|
|
66
|
+
maxHeight?: CssLength;
|
|
67
|
+
/** Explicit width. Freezes the inline axis even when `fieldSizing="content"`. */
|
|
68
|
+
width?: CssLength;
|
|
69
|
+
/** Explicit height. Freezes the block axis even when `fieldSizing="content"`. */
|
|
70
|
+
height?: CssLength;
|
|
71
|
+
/**
|
|
72
|
+
* Maximum width — a guard against an unconstrained `fieldSizing="content"`
|
|
73
|
+
* box escaping its parent container.
|
|
74
|
+
*/
|
|
75
|
+
maxWidth?: CssLength;
|
|
76
|
+
/** Text direction. Default: inherited from the document. */
|
|
77
|
+
dir?: "ltr" | "rtl";
|
|
78
|
+
/**
|
|
79
|
+
* CSS `writing-mode`. With `"vertical-rl"` the sizing axes swap: content
|
|
80
|
+
* growth under `fieldSizing="content"` runs horizontally, not vertically.
|
|
81
|
+
*/
|
|
82
|
+
writingMode?: "horizontal-tb" | "vertical-rl" | "vertical-lr";
|
|
83
|
+
/**
|
|
84
|
+
* When true, pressing Enter (without Shift/Ctrl/Meta/Alt) fires
|
|
85
|
+
* `onSubmitted` with the current text instead of inserting a newline.
|
|
86
|
+
* Shift+Enter (etc.) still inserts a newline. Default: `false`.
|
|
87
|
+
*/
|
|
88
|
+
submitOnEnter?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* **Standalone mode only** (ignored when used inside a `pi/form` card —
|
|
91
|
+
* see below). When true, the textarea keeps its own internal text state
|
|
92
|
+
* so the visible text always updates immediately as the user types, but
|
|
93
|
+
* the outgoing `onChanged` event is only dispatched at a "commit" point
|
|
94
|
+
* instead of on every keystroke:
|
|
95
|
+
*
|
|
96
|
+
* - always on blur,
|
|
97
|
+
* - and, if `debounceMs > 0`, also after that many ms of typing
|
|
98
|
+
* inactivity (a trailing debounce), so the value is committed even if
|
|
99
|
+
* the user never blurs the field (e.g. drives an autosave / API call).
|
|
100
|
+
*
|
|
101
|
+
* Use this to avoid flooding the host app / reducer with an event per
|
|
102
|
+
* keystroke for a card whose `onChanged` handler is expensive.
|
|
103
|
+
*
|
|
104
|
+
* When the card is used inside a `pi/form` (i.e. `name` is set and a
|
|
105
|
+
* `pi/form` ancestor is present), this prop has no effect: form fields
|
|
106
|
+
* always write back to form state on every keystroke via
|
|
107
|
+
* `form.handleChange`, exactly like `pi/input` and `pi/text-field` — the
|
|
108
|
+
* form's own submit action is the natural "commit" point in that case.
|
|
109
|
+
*
|
|
110
|
+
* Default: `false` (dispatches `onChanged` on every keystroke, as
|
|
111
|
+
* before).
|
|
112
|
+
*/
|
|
113
|
+
selfManaged?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Trailing-debounce window (ms) for committing changes while
|
|
116
|
+
* `selfManaged` is true (standalone mode only). `0` (default) means no
|
|
117
|
+
* debounce — the value is only committed on blur. Ignored when
|
|
118
|
+
* `selfManaged` is `false`, or when the card is inside a `pi/form`.
|
|
119
|
+
*/
|
|
120
|
+
debounceMs?: number;
|
|
121
|
+
/** Additional class names merged onto the root `<textarea>`. */
|
|
122
|
+
className?: string;
|
|
123
|
+
/** Additional inline styles merged onto the root `<textarea>` (highest precedence). */
|
|
124
|
+
style?: CSSProperties;
|
|
125
|
+
/**
|
|
126
|
+
* When true, the textarea grabs keyboard focus the first time it is
|
|
127
|
+
* mounted/shown (e.g. when a dialog or drawer opens). Only applies once,
|
|
128
|
+
* on mount — it does not re-focus on subsequent re-renders.
|
|
129
|
+
*/
|
|
130
|
+
autoFocus?: boolean;
|
|
131
|
+
};
|
|
132
|
+
export type PiTextAreaChangedEvent = {
|
|
133
|
+
/** Field name, mirrors the `name` prop if provided. */
|
|
134
|
+
name?: string;
|
|
135
|
+
/** New value after the change. */
|
|
136
|
+
value: string;
|
|
137
|
+
};
|
|
138
|
+
export type PiTextAreaSubmittedEvent = {
|
|
139
|
+
/** Field name, mirrors the `name` prop if provided. */
|
|
140
|
+
name?: string;
|
|
141
|
+
/** The current text at the time Enter was pressed. */
|
|
142
|
+
value: string;
|
|
143
|
+
};
|
|
144
|
+
export type PiTextAreaEvents = {
|
|
145
|
+
onChanged: PiTextAreaChangedEvent;
|
|
146
|
+
onSubmitted: PiTextAreaSubmittedEvent;
|
|
147
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createCardDeclaration as e, createOnAction as t, registerActions as n } from "@pihanga2/core";
|
|
2
|
+
//#region src/cards/textArea/textArea.types.ts
|
|
3
|
+
var r = "pi/text-area", i = e(r), a = n(r, ["changed", "submitted"]), o = t(a.CHANGED), s = t(a.SUBMITTED);
|
|
4
|
+
//#endregion
|
|
5
|
+
export { a as PI_TEXT_AREA_ACTION, r as PI_TEXT_AREA_CARD, i as TextArea, o as onTextAreaChanged, s as onTextAreaSubmitted };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=textArea.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textArea.types.js","names":[],"sources":["../../../src/cards/textArea/textArea.types.ts"],"sourcesContent":["import type {CSSProperties} from \"react\";\nimport {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_TEXT_AREA_CARD = \"pi/text-area\";\n\nexport const TextArea = createCardDeclaration<\n PiTextAreaProps,\n PiTextAreaEvents\n>(PI_TEXT_AREA_CARD);\n\nexport const PI_TEXT_AREA_ACTION = registerActions(PI_TEXT_AREA_CARD, [\n \"changed\",\n \"submitted\",\n]);\n\nexport const onTextAreaChanged = createOnAction<PiTextAreaChangedEvent>(\n PI_TEXT_AREA_ACTION.CHANGED,\n);\n\nexport const onTextAreaSubmitted = createOnAction<PiTextAreaSubmittedEvent>(\n PI_TEXT_AREA_ACTION.SUBMITTED,\n);\n\n/** A CSS length. Numbers are treated as pixels, strings are used verbatim. */\nexport type CssLength = number | string;\n\n/**\n * How the textarea sizes itself:\n * - \"fixed\" (default) — plain `<textarea>` behaviour. Size is governed by\n * `rows`/`cols` (and any explicit `width`/`height`); the user\n * may resize it per the `resize` prop. Never grows with content.\n * - \"content\" — uses the CSS `field-sizing: content` behaviour: the box\n * grows/shrinks to fit its content, clamped by any\n * `minHeight`/`maxHeight`/`width`/`height`/`maxWidth` you set.\n * `rows`/`cols` are ignored by the browser once this is active.\n */\nexport type PiTextAreaFieldSizing = \"fixed\" | \"content\";\n\nexport type PiTextAreaResize = \"none\" | \"vertical\" | \"horizontal\" | \"both\";\n\nexport type PiTextAreaProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its value from form state and writes\n * back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled value used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n value?: string;\n\n /** Placeholder text shown when the box is empty. May contain `\\n`. */\n placeholder?: string;\n\n /** When true, the textarea is disabled and non-interactive. */\n disabled?: boolean;\n\n /** When true, the textarea's value cannot be edited by the user. */\n readOnly?: boolean;\n\n /**\n * Number of visible text lines. Only meaningful when `fieldSizing` is\n * `\"fixed\"` — browsers ignore `rows`/`cols` once `field-sizing: content`\n * is active. Default: `4`.\n */\n rows?: number;\n\n /** Number of visible character columns. See `rows` for caveats. */\n cols?: number;\n\n /** See `PiTextAreaFieldSizing`. Default: `\"fixed\"`. */\n fieldSizing?: PiTextAreaFieldSizing;\n\n /**\n * CSS `resize` behaviour — whether/how the user can drag-resize the box.\n * Default: `\"vertical\"` when `fieldSizing` is `\"fixed\"`, `\"none\"` when\n * `fieldSizing` is `\"content\"` (dragging would otherwise permanently\n * defeat the content-based sizing by writing an inline width/height).\n */\n resize?: PiTextAreaResize;\n\n /** Minimum height. Accepts CSS units like `\"2lh\"`, `\"4rem\"`, or a number of px. */\n minHeight?: CssLength;\n\n /** Maximum height. Once reached, content scrolls instead of growing further. */\n maxHeight?: CssLength;\n\n /** Explicit width. Freezes the inline axis even when `fieldSizing=\"content\"`. */\n width?: CssLength;\n\n /** Explicit height. Freezes the block axis even when `fieldSizing=\"content\"`. */\n height?: CssLength;\n\n /**\n * Maximum width — a guard against an unconstrained `fieldSizing=\"content\"`\n * box escaping its parent container.\n */\n maxWidth?: CssLength;\n\n /** Text direction. Default: inherited from the document. */\n dir?: \"ltr\" | \"rtl\";\n\n /**\n * CSS `writing-mode`. With `\"vertical-rl\"` the sizing axes swap: content\n * growth under `fieldSizing=\"content\"` runs horizontally, not vertically.\n */\n writingMode?: \"horizontal-tb\" | \"vertical-rl\" | \"vertical-lr\";\n\n /**\n * When true, pressing Enter (without Shift/Ctrl/Meta/Alt) fires\n * `onSubmitted` with the current text instead of inserting a newline.\n * Shift+Enter (etc.) still inserts a newline. Default: `false`.\n */\n submitOnEnter?: boolean;\n\n /**\n * **Standalone mode only** (ignored when used inside a `pi/form` card —\n * see below). When true, the textarea keeps its own internal text state\n * so the visible text always updates immediately as the user types, but\n * the outgoing `onChanged` event is only dispatched at a \"commit\" point\n * instead of on every keystroke:\n *\n * - always on blur,\n * - and, if `debounceMs > 0`, also after that many ms of typing\n * inactivity (a trailing debounce), so the value is committed even if\n * the user never blurs the field (e.g. drives an autosave / API call).\n *\n * Use this to avoid flooding the host app / reducer with an event per\n * keystroke for a card whose `onChanged` handler is expensive.\n *\n * When the card is used inside a `pi/form` (i.e. `name` is set and a\n * `pi/form` ancestor is present), this prop has no effect: form fields\n * always write back to form state on every keystroke via\n * `form.handleChange`, exactly like `pi/input` and `pi/text-field` — the\n * form's own submit action is the natural \"commit\" point in that case.\n *\n * Default: `false` (dispatches `onChanged` on every keystroke, as\n * before).\n */\n selfManaged?: boolean;\n\n /**\n * Trailing-debounce window (ms) for committing changes while\n * `selfManaged` is true (standalone mode only). `0` (default) means no\n * debounce — the value is only committed on blur. Ignored when\n * `selfManaged` is `false`, or when the card is inside a `pi/form`.\n */\n debounceMs?: number;\n\n /** Additional class names merged onto the root `<textarea>`. */\n className?: string;\n\n /** Additional inline styles merged onto the root `<textarea>` (highest precedence). */\n style?: CSSProperties;\n\n /**\n * When true, the textarea grabs keyboard focus the first time it is\n * mounted/shown (e.g. when a dialog or drawer opens). Only applies once,\n * on mount — it does not re-focus on subsequent re-renders.\n */\n autoFocus?: boolean;\n};\n\nexport type PiTextAreaChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New value after the change. */\n value: string;\n};\n\nexport type PiTextAreaSubmittedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** The current text at the time Enter was pressed. */\n value: string;\n};\n\nexport type PiTextAreaEvents = {\n onChanged: PiTextAreaChangedEvent;\n onSubmitted: PiTextAreaSubmittedEvent;\n};\n"],"mappings":";;AAOA,IAAa,IAAoB,gBAEpB,IAAW,EAGtB,CAAiB,GAEN,IAAsB,EAAgB,GAAmB,CACpE,WACA,WACF,CAAC,GAEY,IAAoB,EAC/B,EAAoB,OACtB,GAEa,IAAsB,EACjC,EAAoB,SACtB"}
|
|
@@ -3,11 +3,11 @@ export declare const TextField: <S extends import('@pihanga2/core').ReduxState>(
|
|
|
3
3
|
export declare const PI_TEXT_FIELD_ACTION: {
|
|
4
4
|
CHANGED: string;
|
|
5
5
|
};
|
|
6
|
-
export declare const onTextFieldChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').
|
|
6
|
+
export declare const onTextFieldChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
7
7
|
cardID: string;
|
|
8
8
|
} & PiTextFieldChangedEvent>) => void;
|
|
9
9
|
/** @deprecated Use `onTextFieldChanged` instead. */
|
|
10
|
-
export declare const onPiTextFieldChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').
|
|
10
|
+
export declare const onPiTextFieldChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
11
11
|
cardID: string;
|
|
12
12
|
} & PiTextFieldChangedEvent>) => void;
|
|
13
13
|
export type PiTextFieldProps = {
|
|
@@ -38,17 +38,17 @@ export declare const dispatchShowToast: (d: DispatchF, ev: ShowToastEvent) => vo
|
|
|
38
38
|
* });
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
|
-
export declare const onShowToast: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').
|
|
41
|
+
export declare const onShowToast: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
42
42
|
cardID: string;
|
|
43
43
|
} & ShowToastEvent>) => void;
|
|
44
44
|
export declare const PI_TOAST_ACTION: {
|
|
45
45
|
CLOSED: string;
|
|
46
46
|
};
|
|
47
|
-
export declare const onToastClosed: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').
|
|
47
|
+
export declare const onToastClosed: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
48
48
|
cardID: string;
|
|
49
49
|
} & PiToastClosedEvent>) => void;
|
|
50
50
|
/** @deprecated Use `onToastClosed` instead. */
|
|
51
|
-
export declare const onPiToastClosed: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').
|
|
51
|
+
export declare const onPiToastClosed: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
52
52
|
cardID: string;
|
|
53
53
|
} & PiToastClosedEvent>) => void;
|
|
54
54
|
/**
|
|
@@ -3,11 +3,11 @@ export declare const ToggleGroup: <S extends import('@pihanga2/core').ReduxState
|
|
|
3
3
|
export declare const PI_TOGGLE_GROUP_ACTION: {
|
|
4
4
|
CHANGED: string;
|
|
5
5
|
};
|
|
6
|
-
export declare const onToggleGroupChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').
|
|
6
|
+
export declare const onToggleGroupChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
7
7
|
cardID: string;
|
|
8
8
|
} & PiToggleGroupChangedEvent>) => void;
|
|
9
9
|
/** @deprecated Use `onToggleGroupChanged` instead. */
|
|
10
|
-
export declare const onPiToggleGroupChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').
|
|
10
|
+
export declare const onPiToggleGroupChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core/types').PiRegisterMinimal, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
|
|
11
11
|
cardID: string;
|
|
12
12
|
} & PiToggleGroupChangedEvent>) => void;
|
|
13
13
|
export type PiToggleGroupItem = {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/utils.js";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { cva as n } from "class-variance-authority";
|
|
4
|
+
//#region src/components/ui/empty.tsx
|
|
5
|
+
function r({ className: n, ...r }) {
|
|
6
|
+
return /* @__PURE__ */ t("div", {
|
|
7
|
+
"data-slot": "empty",
|
|
8
|
+
className: e("flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance rounded-lg border-dashed p-6 text-center md:p-12", n),
|
|
9
|
+
...r
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
var i = n("mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0", {
|
|
13
|
+
variants: { variant: {
|
|
14
|
+
default: "bg-transparent",
|
|
15
|
+
icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6"
|
|
16
|
+
} },
|
|
17
|
+
defaultVariants: { variant: "default" }
|
|
18
|
+
});
|
|
19
|
+
function a({ className: n, variant: r = "default", ...a }) {
|
|
20
|
+
return /* @__PURE__ */ t("div", {
|
|
21
|
+
"data-slot": "empty-icon",
|
|
22
|
+
"data-variant": r,
|
|
23
|
+
className: e(i({
|
|
24
|
+
variant: r,
|
|
25
|
+
className: n
|
|
26
|
+
})),
|
|
27
|
+
...a
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function o({ className: n, ...r }) {
|
|
31
|
+
return /* @__PURE__ */ t("div", {
|
|
32
|
+
"data-slot": "empty-content",
|
|
33
|
+
className: e("flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm", n),
|
|
34
|
+
...r
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { r as Empty, o as EmptyContent, a as EmptyMedia };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=empty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty.js","names":[],"sources":["../../../src/components/ui/empty.tsx"],"sourcesContent":["import {cva, type VariantProps} from \"class-variance-authority\";\n\nimport {cn} from \"@/lib/utils\";\n\nfunction Empty({className, ...props}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n \"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance rounded-lg border-dashed p-6 text-center md:p-12\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyHeader({className, ...props}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn(\n \"flex max-w-sm flex-col items-center gap-2 text-center\",\n className,\n )}\n {...props}\n />\n );\n}\n\nconst emptyMediaVariants = cva(\n \"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction EmptyMedia({\n className,\n variant = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof emptyMediaVariants>) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({variant, className}))}\n {...props}\n />\n );\n}\n\nfunction EmptyTitle({className, ...props}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-title\"\n className={cn(\"text-lg font-medium tracking-tight\", className)}\n {...props}\n />\n );\n}\n\nfunction EmptyDescription({className, ...props}: React.ComponentProps<\"p\">) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n \"text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyContent({className, ...props}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\n \"flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Empty,\n EmptyHeader,\n EmptyTitle,\n EmptyDescription,\n EmptyContent,\n EmptyMedia,\n};\n"],"mappings":";;;;AAIA,SAAS,EAAM,EAAC,cAAW,GAAG,KAAqC;CACjE,OACE,kBAAC,OAAD;EACE,aAAU;EACV,WAAW,EACT,gIACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAeA,IAAM,IAAqB,EACzB,+FACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,MAAM;CACR,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,SAAS,EAAW,EAClB,cACA,aAAU,WACV,GAAG,KACqE;CACxE,OACE,kBAAC,OAAD;EACE,aAAU;EACV,gBAAc;EACd,WAAW,EAAG,EAAmB;GAAC;GAAS;EAAS,CAAC,CAAC;EACtD,GAAI;CACL,CAAA;AAEL;AAyBA,SAAS,EAAa,EAAC,cAAW,GAAG,KAAqC;CACxE,OACE,kBAAC,OAAD;EACE,aAAU;EACV,WAAW,EACT,iFACA,CACF;EACA,GAAI;CACL,CAAA;AAEL"}
|
package/components/ui/input.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { cn as e } from "../lib/utils.js";
|
|
2
|
-
import "react";
|
|
3
|
-
import { jsx as
|
|
2
|
+
import * as t from "react";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
4
|
//#region src/components/ui/input.tsx
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
var r = t.forwardRef(({ className: t, type: r, ...i }, a) => /* @__PURE__ */ n("input", {
|
|
6
|
+
ref: a,
|
|
7
|
+
type: r,
|
|
8
|
+
"data-slot": "input",
|
|
9
|
+
className: e("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", t),
|
|
10
|
+
...i
|
|
11
|
+
}));
|
|
12
|
+
r.displayName = "Input";
|
|
13
13
|
//#endregion
|
|
14
|
-
export {
|
|
14
|
+
export { r as Input };
|
|
15
15
|
|
|
16
16
|
//# sourceMappingURL=input.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.js","names":[],"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["import * as React from \"react\"
|
|
1
|
+
{"version":3,"file":"input.js","names":[],"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport {cn} from \"@/components/lib/utils\";\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<\"input\">>(\n ({className, type, ...props}, ref) => {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n \"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n className,\n )}\n {...props}\n />\n );\n },\n);\nInput.displayName = \"Input\";\n\nexport {Input};\n"],"mappings":";;;;AAIA,IAAM,IAAQ,EAAM,YACjB,EAAC,cAAW,SAAM,GAAG,KAAQ,MAE1B,kBAAC,SAAD;CACO;CACC;CACN,aAAU;CACV,WAAW,EACT,8bACA,iFACA,0GACA,CACF;CACA,GAAI;AACL,CAAA,CAGP;AACA,EAAM,cAAc"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/utils.js";
|
|
2
|
+
import * as t from "react";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/ui/textarea.tsx
|
|
5
|
+
var r = t.forwardRef(({ className: t, ...r }, i) => /* @__PURE__ */ n("textarea", {
|
|
6
|
+
ref: i,
|
|
7
|
+
"data-slot": "textarea",
|
|
8
|
+
className: e("flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40", t),
|
|
9
|
+
...r
|
|
10
|
+
}));
|
|
11
|
+
r.displayName = "Textarea";
|
|
12
|
+
//#endregion
|
|
13
|
+
export { r as Textarea };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textarea.js","names":[],"sources":["../../../src/components/ui/textarea.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport {cn} from \"@/lib/utils\";\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<\"textarea\">\n>(({className, ...props}, ref) => {\n return (\n <textarea\n ref={ref}\n data-slot=\"textarea\"\n className={cn(\n \"flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40\",\n className,\n )}\n {...props}\n />\n );\n});\nTextarea.displayName = \"Textarea\";\n\nexport {Textarea};\n"],"mappings":";;;;AAIA,IAAM,IAAW,EAAM,YAGpB,EAAC,cAAW,GAAG,KAAQ,MAEtB,kBAAC,YAAD;CACO;CACL,aAAU;CACV,WAAW,EACT,ucACA,CACF;CACA,GAAI;AACL,CAAA,CAEJ;AACD,EAAS,cAAc"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pihanga2/shadcn",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.19",
|
|
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": {
|
|
@@ -48,6 +48,10 @@
|
|
|
48
48
|
"import": "./cards/dropDownMenu/index.js",
|
|
49
49
|
"types": "./cards/dropDownMenu/index.d.ts"
|
|
50
50
|
},
|
|
51
|
+
"./cards/emptyCard": {
|
|
52
|
+
"import": "./cards/emptyCard/index.js",
|
|
53
|
+
"types": "./cards/emptyCard/index.d.ts"
|
|
54
|
+
},
|
|
51
55
|
"./cards/field": {
|
|
52
56
|
"import": "./cards/field/index.js",
|
|
53
57
|
"types": "./cards/field/index.d.ts"
|
|
@@ -112,6 +116,10 @@
|
|
|
112
116
|
"import": "./cards/navbarSearch/index.js",
|
|
113
117
|
"types": "./cards/navbarSearch/index.d.ts"
|
|
114
118
|
},
|
|
119
|
+
"./cards/observable": {
|
|
120
|
+
"import": "./cards/observable/index.js",
|
|
121
|
+
"types": "./cards/observable/index.d.ts"
|
|
122
|
+
},
|
|
115
123
|
"./cards/pageWithNavbar": {
|
|
116
124
|
"import": "./cards/pageWithNavbar/index.js",
|
|
117
125
|
"types": "./cards/pageWithNavbar/index.d.ts"
|
|
@@ -128,6 +136,14 @@
|
|
|
128
136
|
"import": "./cards/resizable/index.js",
|
|
129
137
|
"types": "./cards/resizable/index.d.ts"
|
|
130
138
|
},
|
|
139
|
+
"./cards/resizableColumns": {
|
|
140
|
+
"import": "./cards/resizableColumns/index.js",
|
|
141
|
+
"types": "./cards/resizableColumns/index.d.ts"
|
|
142
|
+
},
|
|
143
|
+
"./cards/resizableGrid": {
|
|
144
|
+
"import": "./cards/resizableGrid/index.js",
|
|
145
|
+
"types": "./cards/resizableGrid/index.d.ts"
|
|
146
|
+
},
|
|
131
147
|
"./cards/scrollbarWithAnnotations": {
|
|
132
148
|
"import": "./cards/scrollbarWithAnnotations/index.js",
|
|
133
149
|
"types": "./cards/scrollbarWithAnnotations/index.d.ts"
|
|
@@ -168,6 +184,10 @@
|
|
|
168
184
|
"import": "./cards/tabs/index.js",
|
|
169
185
|
"types": "./cards/tabs/index.d.ts"
|
|
170
186
|
},
|
|
187
|
+
"./cards/textArea": {
|
|
188
|
+
"import": "./cards/textArea/index.js",
|
|
189
|
+
"types": "./cards/textArea/index.d.ts"
|
|
190
|
+
},
|
|
171
191
|
"./cards/textField": {
|
|
172
192
|
"import": "./cards/textField/index.js",
|
|
173
193
|
"types": "./cards/textField/index.d.ts"
|
|
@@ -217,6 +237,7 @@
|
|
|
217
237
|
"./cards/dialog/index.js",
|
|
218
238
|
"./cards/drawer/index.js",
|
|
219
239
|
"./cards/dropDownMenu/index.js",
|
|
240
|
+
"./cards/emptyCard/index.js",
|
|
220
241
|
"./cards/field/index.js",
|
|
221
242
|
"./cards/fileDrop/index.js",
|
|
222
243
|
"./cards/flexGrid/index.js",
|
|
@@ -233,10 +254,13 @@
|
|
|
233
254
|
"./cards/menu/index.js",
|
|
234
255
|
"./cards/modeToggle/index.js",
|
|
235
256
|
"./cards/navbarSearch/index.js",
|
|
257
|
+
"./cards/observable/index.js",
|
|
236
258
|
"./cards/pageWithNavbar/index.js",
|
|
237
259
|
"./cards/pageWithNavbarMeta/index.js",
|
|
238
260
|
"./cards/pasteTarget/index.js",
|
|
239
261
|
"./cards/resizable/index.js",
|
|
262
|
+
"./cards/resizableColumns/index.js",
|
|
263
|
+
"./cards/resizableGrid/index.js",
|
|
240
264
|
"./cards/scrollbarWithAnnotations/index.js",
|
|
241
265
|
"./cards/select/index.js",
|
|
242
266
|
"./cards/sheetCard/index.js",
|
|
@@ -247,6 +271,7 @@
|
|
|
247
271
|
"./cards/suspense/index.js",
|
|
248
272
|
"./cards/switch/index.js",
|
|
249
273
|
"./cards/tabs/index.js",
|
|
274
|
+
"./cards/textArea/index.js",
|
|
250
275
|
"./cards/textField/index.js",
|
|
251
276
|
"./cards/toast/index.js",
|
|
252
277
|
"./cards/toggleGroup/index.js",
|
|
@@ -270,10 +295,11 @@
|
|
|
270
295
|
"peerDependencies": {
|
|
271
296
|
"react": "^19.1.0",
|
|
272
297
|
"react-dom": "^19.1.0",
|
|
273
|
-
"@pihanga2/core": "
|
|
298
|
+
"@pihanga2/core": "0.3.38",
|
|
274
299
|
"@pihanga2/cards": "*"
|
|
275
300
|
},
|
|
276
301
|
"dependencies": {
|
|
302
|
+
"@pihanga2/shadcn": "UNKNOWN - add to root package.json",
|
|
277
303
|
"@radix-ui/react-collapsible": "^1.1.20",
|
|
278
304
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
279
305
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|