@donotdev/components 0.0.13 → 0.0.14
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/dist/advanced/Code/CodeContent.d.ts.map +1 -1
- package/dist/advanced/Code/CodeContent.js +5 -1
- package/dist/advanced/Code/CodeSkeleton.d.ts.map +1 -1
- package/dist/advanced/Code/CodeSkeleton.js +2 -1
- package/dist/advanced/JsonViewer/JsonViewer.d.ts.map +1 -1
- package/dist/advanced/JsonViewer/JsonViewer.js +2 -1
- package/dist/atomic/Button/index.d.ts.map +1 -1
- package/dist/atomic/Checkbox/index.d.ts +16 -2
- package/dist/atomic/Checkbox/index.d.ts.map +1 -1
- package/dist/atomic/Checkbox/index.js +20 -4
- package/dist/atomic/Collapsible/index.d.ts.map +1 -1
- package/dist/atomic/Collapsible/index.js +5 -1
- package/dist/atomic/Icons/Partner/providerIcons.d.ts.map +1 -1
- package/dist/atomic/Icons/Partner/providerIcons.js +17 -1
- package/dist/atomic/Input/index.d.ts +6 -1
- package/dist/atomic/Input/index.d.ts.map +1 -1
- package/dist/atomic/Input/index.js +10 -5
- package/dist/atomic/Label/FloatingLabel.d.ts +3 -1
- package/dist/atomic/Label/FloatingLabel.d.ts.map +1 -1
- package/dist/atomic/Label/FloatingLabel.js +2 -2
- package/dist/atomic/Pagination/index.d.ts +7 -29
- package/dist/atomic/Pagination/index.d.ts.map +1 -1
- package/dist/atomic/Pagination/index.js +101 -71
- package/dist/atomic/PasswordInput/index.d.ts.map +1 -1
- package/dist/atomic/PasswordInput/index.js +1 -1
- package/dist/atomic/RangeInput/index.d.ts +45 -0
- package/dist/atomic/RangeInput/index.d.ts.map +1 -0
- package/dist/atomic/RangeInput/index.js +63 -0
- package/dist/atomic/Select/index.d.ts.map +1 -1
- package/dist/atomic/Select/index.js +1 -1
- package/dist/atomic/Slider/index.d.ts.map +1 -1
- package/dist/atomic/Slider/index.js +7 -4
- package/dist/atomic/Table/index.d.ts +18 -5
- package/dist/atomic/Table/index.d.ts.map +1 -1
- package/dist/atomic/Table/index.js +91 -31
- package/dist/atomic/Textarea/index.d.ts +4 -0
- package/dist/atomic/Textarea/index.d.ts.map +1 -1
- package/dist/atomic/Textarea/index.js +3 -3
- package/dist/atomic/Toaster/Toast.types.d.ts +17 -0
- package/dist/atomic/Toaster/Toast.types.d.ts.map +1 -0
- package/dist/atomic/Toaster/Toast.types.js +2 -0
- package/dist/atomic/Toaster/ToastPrimitive.d.ts +1 -1
- package/dist/atomic/Toaster/ToastPrimitive.d.ts.map +1 -1
- package/dist/atomic/VideoPlayer/index.d.ts +11 -1
- package/dist/atomic/VideoPlayer/index.d.ts.map +1 -1
- package/dist/atomic/VideoPlayer/index.js +6 -8
- package/dist/atomic/index.d.ts +2 -0
- package/dist/atomic/index.d.ts.map +1 -1
- package/dist/atomic/index.js +1 -0
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useToast.d.ts +1 -8
- package/dist/hooks/useToast.d.ts.map +1 -1
- package/dist/hooks/useToast.js +1 -0
- package/dist/index.js +4 -4
- package/dist/styles/index.css +186 -72
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { InputHTMLAttributes } from 'react';
|
|
2
|
+
import './RangeInput.css';
|
|
3
|
+
export interface RangeInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value'> {
|
|
4
|
+
/** Label for the range (single FloatingLabel wrapping both inputs) */
|
|
5
|
+
label?: string;
|
|
6
|
+
/** Placeholder for min input */
|
|
7
|
+
minPlaceholder?: string;
|
|
8
|
+
/** Placeholder for max input */
|
|
9
|
+
maxPlaceholder?: string;
|
|
10
|
+
/** Current min value */
|
|
11
|
+
minValue?: string;
|
|
12
|
+
/** Current max value */
|
|
13
|
+
maxValue?: string;
|
|
14
|
+
/** Actual min value from data (for auto-populate on focus) */
|
|
15
|
+
actualMin?: string | number;
|
|
16
|
+
/** Actual max value from data (for auto-populate on focus) */
|
|
17
|
+
actualMax?: string | number;
|
|
18
|
+
/** Change handler: (min, max) => void */
|
|
19
|
+
onChange: (min: string, max: string) => void;
|
|
20
|
+
/** Clear handler - required, X button always visible */
|
|
21
|
+
onClear: () => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* RangeInput - Two-input component for min/max ranges
|
|
25
|
+
*
|
|
26
|
+
* Features:
|
|
27
|
+
* - Single FloatingLabel wrapping both inputs (when label provided)
|
|
28
|
+
* - Auto-populates with actual data min/max on focus if empty
|
|
29
|
+
* - Selects all text on focus
|
|
30
|
+
* - Clear button always visible (disabled when empty)
|
|
31
|
+
*
|
|
32
|
+
* @component
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* <RangeInput
|
|
36
|
+
* type="number"
|
|
37
|
+
* label="Price"
|
|
38
|
+
* onChange={(min, max) => setFilter({ min, max })}
|
|
39
|
+
* onClear={() => setFilter({ min: '', max: '' })}
|
|
40
|
+
* />
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function RangeInput({ type, label, minPlaceholder, maxPlaceholder, minValue, maxValue, actualMin, actualMax, min, max, onChange, onClear, ...props }: RangeInputProps): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
export default RangeInput;
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/RangeInput/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,kBAAkB,CAAC;AAE1B,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,UAAU,GAAG,OAAO,CACrB;IACC,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,wDAAwD;IACxD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAe,EACf,KAAK,EACL,cAAsB,EACtB,cAAsB,EACtB,QAAa,EACb,QAAa,EACb,SAAS,EACT,SAAS,EACT,GAAG,EACH,GAAG,EACH,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACT,EAAE,eAAe,2CA+EjB;AAED,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// packages/components/src/atomic/RangeInput/index.tsx
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview RangeInput component
|
|
5
|
+
* @description Two-input range component for min/max values (e.g., price ranges, date ranges)
|
|
6
|
+
*
|
|
7
|
+
* @version 0.0.2
|
|
8
|
+
* @since 0.0.1
|
|
9
|
+
* @author AMBROISE PARK Consulting
|
|
10
|
+
*/
|
|
11
|
+
import { X } from 'lucide-react';
|
|
12
|
+
import Button from '../Button';
|
|
13
|
+
import Input from '../Input';
|
|
14
|
+
import { FloatingLabel } from '../Label';
|
|
15
|
+
import Text from '../Text';
|
|
16
|
+
import './RangeInput.css';
|
|
17
|
+
/**
|
|
18
|
+
* RangeInput - Two-input component for min/max ranges
|
|
19
|
+
*
|
|
20
|
+
* Features:
|
|
21
|
+
* - Single FloatingLabel wrapping both inputs (when label provided)
|
|
22
|
+
* - Auto-populates with actual data min/max on focus if empty
|
|
23
|
+
* - Selects all text on focus
|
|
24
|
+
* - Clear button always visible (disabled when empty)
|
|
25
|
+
*
|
|
26
|
+
* @component
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <RangeInput
|
|
30
|
+
* type="number"
|
|
31
|
+
* label="Price"
|
|
32
|
+
* onChange={(min, max) => setFilter({ min, max })}
|
|
33
|
+
* onClear={() => setFilter({ min: '', max: '' })}
|
|
34
|
+
* />
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function RangeInput({ type = 'number', label, minPlaceholder = 'Min', maxPlaceholder = 'Max', minValue = '', maxValue = '', actualMin, actualMax, min, max, onChange, onClear, ...props }) {
|
|
38
|
+
const handleMinFocus = (e) => {
|
|
39
|
+
e.target.select();
|
|
40
|
+
if (!minValue &&
|
|
41
|
+
actualMin !== null &&
|
|
42
|
+
actualMin !== undefined &&
|
|
43
|
+
actualMin !== '') {
|
|
44
|
+
onChange(String(actualMin), maxValue);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const handleMaxFocus = (e) => {
|
|
48
|
+
e.target.select();
|
|
49
|
+
if (!maxValue &&
|
|
50
|
+
actualMax !== null &&
|
|
51
|
+
actualMax !== undefined &&
|
|
52
|
+
actualMax !== '') {
|
|
53
|
+
onChange(minValue, String(actualMax));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const hasValue = !!(minValue || maxValue);
|
|
57
|
+
const inputs = (_jsxs(_Fragment, { children: [_jsx(Input, { type: type, placeholder: minPlaceholder, value: minValue, min: min, max: max, bare: true, onFocus: handleMinFocus, onChange: (e) => onChange(e.target.value, maxValue), ...props }), _jsx(Text, { level: "small", variant: "muted", className: "dndev-range-input-separator", children: "\u2013" }), _jsx(Input, { type: type, placeholder: maxPlaceholder, value: maxValue, min: min, max: max, bare: true, onFocus: handleMaxFocus, onChange: (e) => onChange(minValue, e.target.value), ...props }), _jsx(Button, { icon: X, variant: "ghost", display: "compact", onClick: onClear, disabled: !hasValue, "aria-label": "Clear", className: "dndev-range-input-clear" })] }));
|
|
58
|
+
if (label) {
|
|
59
|
+
return (_jsx(FloatingLabel, { label: label, className: "dndev-range-input", children: inputs }));
|
|
60
|
+
}
|
|
61
|
+
return _jsx("div", { className: "dndev-range-input", children: inputs });
|
|
62
|
+
}
|
|
63
|
+
export default RangeInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Select/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,mBAON,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,WAAY,SAAQ,IAAI,CACvC,cAAc,CAAC,OAAO,mBAAmB,CAAC,EAC1C,UAAU,CACX;IACC,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mGAAmG;IACnG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,MAAM,GAAI,uHAYb,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Select/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,mBAON,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,WAAY,SAAQ,IAAI,CACvC,cAAc,CAAC,OAAO,mBAAmB,CAAC,EAC1C,UAAU,CACX;IACC,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mGAAmG;IACnG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,MAAM,GAAI,uHAYb,WAAW,4CAyHb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -40,7 +40,7 @@ const Select = ({ value, onValueChange, placeholder = 'Select an option...', opt
|
|
|
40
40
|
const id = useId();
|
|
41
41
|
const [isOpen, setIsOpen] = useState(false);
|
|
42
42
|
const hasLabel = !!label;
|
|
43
|
-
const triggerElement = (_jsxs(SelectTriggerPrimitive, { id: id, className: "dndev-input dndev-select-trigger", disabled: disabled, children: [isLoading ? (_jsxs("div", { className: "dndev-select-loading-container", children: [_jsx("div", { className: "dndev-animate-spin dndev-select-loading-spinner" }), _jsx("span", { children: "Loading..." })] })) : (_jsx(SelectValuePrimitive, { placeholder: placeholder })), _jsx(SelectRadix.Icon, { asChild: true, children: _jsx(ChevronDown, {}) })] }));
|
|
43
|
+
const triggerElement = (_jsxs(SelectTriggerPrimitive, { id: id, className: "dndev-input dndev-select-trigger", disabled: disabled, "data-bare": hasLabel || undefined, children: [isLoading ? (_jsxs("div", { className: "dndev-select-loading-container", children: [_jsx("div", { className: "dndev-animate-spin dndev-select-loading-spinner" }), _jsx("span", { children: "Loading..." })] })) : (_jsx(SelectValuePrimitive, { placeholder: placeholder })), _jsx(SelectRadix.Icon, { asChild: true, children: _jsx(ChevronDown, {}) })] }));
|
|
44
44
|
const customTrigger = trigger ? (_jsx(SelectTriggerPrimitive, { asChild: true, disabled: disabled, className: "dndev-input dndev-select-trigger", children: trigger })) : hasLabel ? (_jsx(FloatingLabel, { htmlFor: id, label: label, disabled: disabled, required: required, children: triggerElement })) : (triggerElement);
|
|
45
45
|
return (_jsxs(SelectRootPrimitive, { value: value, onValueChange: onValueChange, defaultValue: defaultValue, disabled: disabled, onOpenChange: setIsOpen, ...props, children: [customTrigger, _jsx(SelectRadix.Portal, { children: _jsx(SelectContentPrimitive, { className: "dndev-floating dndev-menu-content dndev-z-tooltip dndev-select-content", position: "popper", side: "bottom", sideOffset: 4, align: "start", "data-glow": "blank", children: _jsx(SelectRadix.Viewport, { children: _jsx(ScrollArea, { className: "dndev-menu-scroll-area", end: true, children: options.map((option) => {
|
|
46
46
|
if (option.value === '__label__') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Slider/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAI1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,WAAY,SAAQ,cAAc,CACjD,OAAO,eAAe,CAAC,IAAI,CAC5B;IACC,6BAA6B;IAC7B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,yBAAyB;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAoBD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,MAAM,GAAI,kEAOb,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Slider/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAI1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,WAAY,SAAQ,cAAc,CACjD,OAAO,eAAe,CAAC,IAAI,CAC5B;IACC,6BAA6B;IAC7B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,yBAAyB;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAoBD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,MAAM,GAAI,kEAOb,WAAW,4CAmCb,CAAC;AAEF,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,eAAe,IAAI,cAAc,EAAE,CAAC;AAC9D,YAAY,EAAE,cAAc,IAAI,aAAa,EAAE,CAAC"}
|
|
@@ -47,10 +47,13 @@ const sliderVariants = cva('dndev-slider', {
|
|
|
47
47
|
const Slider = ({ className, variant, showValue, value, defaultValue, ...props }) => {
|
|
48
48
|
const variantAttrs = getVariantDataAttrs({ variant });
|
|
49
49
|
const currentValue = value ?? defaultValue;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
// Handle array values (for range sliders) or single values
|
|
51
|
+
const values = Array.isArray(currentValue)
|
|
52
|
+
? currentValue
|
|
53
|
+
: currentValue !== undefined
|
|
54
|
+
? [currentValue]
|
|
55
|
+
: [];
|
|
56
|
+
return (_jsx("div", { className: "dndev-slider-container", children: _jsxs(SliderPrimitive.Root, { className: cn(sliderVariants({ variant }), className), value: value, defaultValue: defaultValue, ...variantAttrs, ...props, children: [_jsx(SliderPrimitive.Track, { className: cn('dndev-slider-track'), children: _jsx(SliderPrimitive.Range, { className: cn('dndev-slider-range') }) }), values.map((val, index) => (_jsx(SliderPrimitive.Thumb, { className: cn('dndev-slider-thumb'), children: showValue && val !== undefined && (_jsx("span", { className: "dndev-slider-value", children: val })) }, index)))] }) }));
|
|
54
57
|
};
|
|
55
58
|
export default Slider;
|
|
56
59
|
export { SliderPrimitive, CONTROL_VARIANT as SLIDER_VARIANT };
|
|
@@ -18,6 +18,7 @@ export interface TableColumn<T = any> {
|
|
|
18
18
|
title: string | ReactNode;
|
|
19
19
|
dataIndex?: keyof T;
|
|
20
20
|
sortable?: boolean;
|
|
21
|
+
/** Enable column header filter (Excel-style dropdown) */
|
|
21
22
|
filterable?: boolean;
|
|
22
23
|
/**
|
|
23
24
|
* Render prop for custom cell content - RENDER PROP EXCEPTION
|
|
@@ -56,12 +57,26 @@ export interface DataTableProps<T = any> {
|
|
|
56
57
|
selectable?: boolean;
|
|
57
58
|
/** Enable search */
|
|
58
59
|
searchable?: boolean;
|
|
59
|
-
/** Enable filtering (placeholder UI) */
|
|
60
|
-
filterable?: boolean;
|
|
61
60
|
/** Enable pagination */
|
|
62
61
|
pagination?: boolean;
|
|
62
|
+
/** Current page (1-indexed) */
|
|
63
|
+
currentPage?: number;
|
|
63
64
|
/** Page size */
|
|
64
65
|
pageSize?: number;
|
|
66
|
+
/** Total number of items (for server-side pagination) */
|
|
67
|
+
total?: number;
|
|
68
|
+
/** Callback when page changes */
|
|
69
|
+
onPageChange?: (page: number) => void;
|
|
70
|
+
/** Callback when page size changes */
|
|
71
|
+
onPageSizeChange?: (pageSize: number) => void;
|
|
72
|
+
/** Label for "Showing X to Y of Z" text (default: "Showing {{from}} to {{to}} of {{total}} results") */
|
|
73
|
+
showingLabel?: string;
|
|
74
|
+
/** Label for previous button (passed to Pagination) */
|
|
75
|
+
paginationPreviousLabel?: string;
|
|
76
|
+
/** Label for next button (passed to Pagination) */
|
|
77
|
+
paginationNextLabel?: string;
|
|
78
|
+
/** Placeholder for items per page selector (passed to Pagination) */
|
|
79
|
+
paginationItemsPerPagePlaceholder?: string;
|
|
65
80
|
/** Loading state */
|
|
66
81
|
loading?: boolean;
|
|
67
82
|
/** Excel-like grid lines (borders on all cells) */
|
|
@@ -72,8 +87,6 @@ export interface DataTableProps<T = any> {
|
|
|
72
87
|
onSelect?: (selectedRows: T[]) => void;
|
|
73
88
|
/** Callback when search query changes */
|
|
74
89
|
onSearch?: (query: string) => void;
|
|
75
|
-
/** Callback when filters change */
|
|
76
|
-
onFilter?: (filters: Record<string, any>) => void;
|
|
77
90
|
/** Callback when a row is clicked */
|
|
78
91
|
onRowClick?: (row: T) => void;
|
|
79
92
|
/** Additional CSS classes */
|
|
@@ -110,7 +123,7 @@ declare function TableCaption({ className, ...props }: HTMLAttributes<HTMLTableC
|
|
|
110
123
|
* @param {DataTableProps} props - The props for the data table
|
|
111
124
|
* @returns {ReactNode} The rendered data table
|
|
112
125
|
*/
|
|
113
|
-
declare const DataTable: <T = any>({ data, columns, sortable, selectable, searchable,
|
|
126
|
+
declare const DataTable: <T = any>({ data, columns, sortable, selectable, searchable, pagination, currentPage: currentPageProp, pageSize: pageSizeProp, total: totalProp, onPageChange, onPageSizeChange, showingLabel, paginationPreviousLabel, paginationNextLabel, paginationItemsPerPagePlaceholder, loading, gridLines, onSort, onSelect, onSearch, onRowClick, className, }: DataTableProps<T>) => ReactNode;
|
|
114
127
|
export default Table;
|
|
115
128
|
export { TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption, DataTable, };
|
|
116
129
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Table/index.tsx"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,cAAc,EAEpB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Table/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -8,13 +8,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
* @since 0.0.1
|
|
9
9
|
* @author AMBROISE PARK Consulting
|
|
10
10
|
*/
|
|
11
|
-
import { ChevronUp, ChevronDown, Search
|
|
11
|
+
import { ChevronUp, ChevronDown, Search } from 'lucide-react';
|
|
12
12
|
import { useState, useMemo, } from 'react';
|
|
13
13
|
import { cn } from '../../utils/helpers';
|
|
14
14
|
import Button, { BUTTON_VARIANT } from '../Button';
|
|
15
15
|
import Checkbox from '../Checkbox';
|
|
16
16
|
import Input from '../Input';
|
|
17
|
-
import
|
|
17
|
+
import Pagination from '../Pagination';
|
|
18
|
+
import Select from '../Select';
|
|
18
19
|
import Stack from '../Stack';
|
|
19
20
|
import Text from '../Text';
|
|
20
21
|
import './Table.css';
|
|
@@ -66,12 +67,38 @@ function TableCaption({ className, ...props }) {
|
|
|
66
67
|
* @param {DataTableProps} props - The props for the data table
|
|
67
68
|
* @returns {ReactNode} The rendered data table
|
|
68
69
|
*/
|
|
69
|
-
const DataTable = ({ data, columns, sortable = true, selectable = false, searchable = true,
|
|
70
|
+
const DataTable = ({ data, columns, sortable = true, selectable = false, searchable = true, pagination = true, currentPage: currentPageProp, pageSize: pageSizeProp, total: totalProp, onPageChange, onPageSizeChange, showingLabel, paginationPreviousLabel, paginationNextLabel, paginationItemsPerPagePlaceholder, loading = false, gridLines = false, onSort, onSelect, onSearch, onRowClick, className, }) => {
|
|
70
71
|
const [sortColumn, setSortColumn] = useState('');
|
|
71
72
|
const [sortDirection, setSortDirection] = useState('asc');
|
|
72
73
|
const [searchQuery, setSearchQuery] = useState('');
|
|
73
74
|
const [selectedRows, setSelectedRows] = useState([]);
|
|
74
|
-
|
|
75
|
+
// Page size state (for client-side pagination) - default 12
|
|
76
|
+
const [internalPageSize, setInternalPageSize] = useState(12);
|
|
77
|
+
const effectivePageSize = pageSizeProp ?? internalPageSize;
|
|
78
|
+
// Controlled vs uncontrolled pagination
|
|
79
|
+
const isControlledPagination = currentPageProp !== undefined && onPageChange !== undefined;
|
|
80
|
+
const [internalPage, setInternalPage] = useState(1);
|
|
81
|
+
const currentPage = isControlledPagination ? currentPageProp : internalPage;
|
|
82
|
+
const handlePageChange = (page) => {
|
|
83
|
+
if (isControlledPagination) {
|
|
84
|
+
onPageChange?.(page);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
setInternalPage(page);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
// Handle page size change
|
|
91
|
+
const handlePageSizeChange = (newPageSize) => {
|
|
92
|
+
if (onPageSizeChange) {
|
|
93
|
+
// Controlled mode (server-side)
|
|
94
|
+
onPageSizeChange(newPageSize);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Uncontrolled mode (client-side) - update internal state
|
|
98
|
+
setInternalPageSize(newPageSize);
|
|
99
|
+
setInternalPage(1); // Reset to page 1
|
|
100
|
+
}
|
|
101
|
+
};
|
|
75
102
|
// Filter and sort data
|
|
76
103
|
const processedData = useMemo(() => {
|
|
77
104
|
let filtered = data;
|
|
@@ -98,11 +125,19 @@ const DataTable = ({ data, columns, sortable = true, selectable = false, searcha
|
|
|
98
125
|
}
|
|
99
126
|
return filtered;
|
|
100
127
|
}, [data, searchQuery, sortColumn, sortDirection, columns]);
|
|
101
|
-
// Pagination
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
// Pagination: use server-side total if provided, otherwise client-side
|
|
129
|
+
const total = totalProp ?? processedData.length;
|
|
130
|
+
// Handle "All" case (pageSize = 0 means show all)
|
|
131
|
+
const isShowingAll = effectivePageSize === 0;
|
|
132
|
+
const pageSize = isShowingAll ? total : effectivePageSize;
|
|
133
|
+
const totalPages = isShowingAll ? 1 : Math.ceil(total / pageSize);
|
|
134
|
+
// For server-side pagination, data is already paginated - use as-is
|
|
135
|
+
// For client-side pagination, slice the data
|
|
136
|
+
const displayData = isControlledPagination && totalProp !== undefined
|
|
137
|
+
? processedData // Server-side: data already paginated
|
|
138
|
+
: pagination && !isShowingAll
|
|
139
|
+
? processedData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
|
|
140
|
+
: processedData;
|
|
106
141
|
const handleSort = (column) => {
|
|
107
142
|
if (!sortable)
|
|
108
143
|
return;
|
|
@@ -112,7 +147,7 @@ const DataTable = ({ data, columns, sortable = true, selectable = false, searcha
|
|
|
112
147
|
onSort?.(column, newDirection);
|
|
113
148
|
};
|
|
114
149
|
const handleSelectAll = (checked) => {
|
|
115
|
-
const newSelection = checked ?
|
|
150
|
+
const newSelection = checked ? displayData : [];
|
|
116
151
|
setSelectedRows(newSelection);
|
|
117
152
|
onSelect?.(newSelection);
|
|
118
153
|
};
|
|
@@ -127,12 +162,12 @@ const DataTable = ({ data, columns, sortable = true, selectable = false, searcha
|
|
|
127
162
|
setSearchQuery(query);
|
|
128
163
|
onSearch?.(query);
|
|
129
164
|
};
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return (_jsxs(Stack, { gap: "medium", children: [
|
|
135
|
-
|
|
165
|
+
// Industry standard pattern: When loading, pass empty rows to render actual structure
|
|
166
|
+
// Component will detect empty data and render skeleton bars in cells
|
|
167
|
+
const skeletonRows = Array.from({ length: 3 }, () => ({}));
|
|
168
|
+
const finalDisplayData = loading ? skeletonRows : displayData;
|
|
169
|
+
return (_jsxs(Stack, { gap: "medium", children: [searchable && (_jsxs(Stack, { direction: "row", align: "center", className: "dndev-relative dndev-flex-1 dndev-table-search-container", children: [_jsx(Search, { className: "dndev-table-search-icon" }), _jsx(Input, { placeholder: "Search...", value: searchQuery, onChange: (e) => handleSearch(e.target.value), className: "dndev-table-search-input" })] })), _jsxs(Table, { className: cn(gridLines && 'dndev-table-grid'), children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [selectable && (_jsx(TableHead, { className: "dndev-w-touch", children: _jsx(Checkbox, { checked: selectedRows.length === displayData.length &&
|
|
170
|
+
displayData.length > 0, onCheckedChange: handleSelectAll, "aria-label": "Select all rows" }) })), columns.map((column) => (_jsx(TableHead, { className: cn(column.sortable && 'dndev-cursor-pointer'), "data-sortable": column.sortable, "data-align": column.align, style: { width: column.width }, onClick: (e) => {
|
|
136
171
|
// Only sort if clicking on header, not on interactive elements (buttons, inputs, etc.)
|
|
137
172
|
if (column.sortable) {
|
|
138
173
|
const target = e.target;
|
|
@@ -141,22 +176,47 @@ const DataTable = ({ data, columns, sortable = true, selectable = false, searcha
|
|
|
141
176
|
handleSort(column.key);
|
|
142
177
|
}
|
|
143
178
|
}
|
|
144
|
-
}, children: _jsxs(Stack, { direction: "row", align: "center", gap: "tight", children: [typeof column.title === 'string' ? (_jsx(Text, { level: "body",
|
|
145
|
-
sortColumn === column.key
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
179
|
+
}, children: _jsxs(Stack, { direction: "row", align: "center", justify: column.align || 'start', gap: "tight", children: [typeof column.title === 'string' ? (_jsx(Text, { level: "body", children: column.title })) : (column.title), column.sortable &&
|
|
180
|
+
(sortColumn === column.key ? (sortDirection === 'asc' ? (_jsx(ChevronUp, { className: "dndev-size-md" })) : (_jsx(ChevronDown, { className: "dndev-size-md" }))) : (_jsx(ChevronUp, { className: "dndev-size-md", style: { opacity: 0.3 } })))] }) }, column.key)))] }) }), _jsx(TableBody, { children: finalDisplayData.map((row, index) => {
|
|
181
|
+
const isSkeletonRow = loading &&
|
|
182
|
+
Object.keys(row).length === 0;
|
|
183
|
+
return (_jsxs(TableRow, { onClick: (e) => {
|
|
184
|
+
if (onRowClick && !isSkeletonRow) {
|
|
185
|
+
const target = e.target;
|
|
186
|
+
// Prevent row click if clicking interactive elements
|
|
187
|
+
const isInteractive = target.closest('button, a, input, [role="button"], label');
|
|
188
|
+
if (!isInteractive) {
|
|
189
|
+
onRowClick(row);
|
|
190
|
+
}
|
|
153
191
|
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
192
|
+
}, className: cn(isSkeletonRow && 'dndev-skeleton-row', onRowClick &&
|
|
193
|
+
!isSkeletonRow &&
|
|
194
|
+
'dndev-cursor-pointer dndev-hover-bg-muted'), children: [selectable && (_jsx(TableCell, { children: isSkeletonRow ? (_jsx("div", { className: "dndev-skeleton dndev-skeleton-pulse", style: {
|
|
195
|
+
width: 'var(--icon-md)',
|
|
196
|
+
height: 'var(--icon-md)',
|
|
197
|
+
borderRadius: 'var(--radius)',
|
|
198
|
+
}, "aria-hidden": "true" })) : (_jsx(Checkbox, { checked: selectedRows.includes(row), onCheckedChange: (checked) => handleSelectRow(row, !!checked), "aria-label": `Select row ${index + 1}` })) })), columns.map((column) => {
|
|
199
|
+
const cellValue = column.dataIndex
|
|
200
|
+
? row[column.dataIndex]
|
|
201
|
+
: null;
|
|
202
|
+
const isEmpty = cellValue === null ||
|
|
203
|
+
cellValue === undefined ||
|
|
204
|
+
cellValue === '';
|
|
205
|
+
// Always call render function if it exists (for action columns, etc.)
|
|
206
|
+
// Let the render function decide what to show for empty/skeleton states
|
|
207
|
+
if (column.render) {
|
|
208
|
+
return (_jsx(TableCell, { "data-align": column.align, children: column.render(cellValue, row, index) }, column.key));
|
|
209
|
+
}
|
|
210
|
+
// For data columns: show skeleton only when loading AND empty
|
|
211
|
+
// When not loading but empty, show empty string (fallback)
|
|
212
|
+
return (_jsx(TableCell, { "data-align": column.align, children: isSkeletonRow ? (_jsx("div", { className: "dndev-skeleton dndev-skeleton-pulse", style: {
|
|
213
|
+
height: 'var(--gap-md)',
|
|
214
|
+
width: index % 2 === 0 ? '80%' : '60%',
|
|
215
|
+
borderRadius: 'var(--radius)',
|
|
216
|
+
}, "aria-hidden": "true" })) : isEmpty ? ('' // Empty state - show nothing, not skeleton
|
|
217
|
+
) : (String(cellValue || '')) }, column.key));
|
|
218
|
+
})] }, index));
|
|
219
|
+
}) })] }), pagination && totalPages > 1 && (_jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: handlePageChange, pageSize: pageSize, total: total, onPageSizeChange: handlePageSizeChange, showingLabel: showingLabel, previousLabel: paginationPreviousLabel, nextLabel: paginationNextLabel, itemsPerPagePlaceholder: paginationItemsPerPagePlaceholder }))] }));
|
|
160
220
|
};
|
|
161
221
|
export default Table;
|
|
162
222
|
export { TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption, DataTable, };
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ComponentPropsWithRef } from 'react';
|
|
2
2
|
export interface TextareaProps extends ComponentPropsWithRef<'textarea'> {
|
|
3
|
+
/**
|
|
4
|
+
* Bare mode - no border/shadow (for use inside FloatingLabel or custom wrappers)
|
|
5
|
+
*/
|
|
6
|
+
bare?: boolean;
|
|
3
7
|
}
|
|
4
8
|
/**
|
|
5
9
|
* Textarea component with ref forwarding.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Textarea/index.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAEnD,MAAM,WAAW,aAAc,SAAQ,qBAAqB,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Textarea/index.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAEnD,MAAM,WAAW,aAAc,SAAQ,qBAAqB,CAAC,UAAU,CAAC;IACtE;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,QAAA,MAAM,QAAQ,4HAWb,CAAC;AAIF,eAAe,QAAQ,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* @fileoverview Textarea component
|
|
5
5
|
* @description Accessible textarea component with mobile-friendly touch targets
|
|
6
6
|
*
|
|
7
|
-
* @version 0.0.
|
|
7
|
+
* @version 0.0.2
|
|
8
8
|
* @since 0.0.1
|
|
9
9
|
* @author AMBROISE PARK Consulting
|
|
10
10
|
*/
|
|
@@ -13,8 +13,8 @@ import { cn } from '../../utils/helpers';
|
|
|
13
13
|
/**
|
|
14
14
|
* Textarea component with ref forwarding.
|
|
15
15
|
*/
|
|
16
|
-
const Textarea = forwardRef(({ className, ...props }, ref) => {
|
|
17
|
-
return (_jsx("textarea", { ref: ref, className: cn('dndev-input', className), ...props }));
|
|
16
|
+
const Textarea = forwardRef(({ className, bare, ...props }, ref) => {
|
|
17
|
+
return (_jsx("textarea", { ref: ref, className: cn('dndev-input', className), "data-bare": bare || undefined, ...props }));
|
|
18
18
|
});
|
|
19
19
|
Textarea.displayName = 'Textarea';
|
|
20
20
|
export default Textarea;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Toast Types
|
|
3
|
+
* @description Type definitions for toast notifications
|
|
4
|
+
*
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @since 0.0.1
|
|
7
|
+
* @author AMBROISE PARK Consulting
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Toast type variants
|
|
11
|
+
*
|
|
12
|
+
* @version 0.0.1
|
|
13
|
+
* @since 0.0.1
|
|
14
|
+
* @author AMBROISE PARK Consulting
|
|
15
|
+
*/
|
|
16
|
+
export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info';
|
|
17
|
+
//# sourceMappingURL=Toast.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.types.d.ts","sourceRoot":"","sources":["../../../src/atomic/Toaster/Toast.types.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
10
10
|
import { type VariantProps } from 'class-variance-authority';
|
|
11
|
-
import type { ToastType } from '
|
|
11
|
+
import type { ToastType } from './Toast.types';
|
|
12
12
|
import type { ComponentProps, ReactElement } from 'react';
|
|
13
13
|
declare const ToastProvider: import("react").FC<ToastPrimitives.ToastProviderProps>;
|
|
14
14
|
declare function ToastViewport({ className, ...props }: ComponentProps<typeof ToastPrimitives.Viewport>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToastPrimitive.d.ts","sourceRoot":"","sources":["../../../src/atomic/Toaster/ToastPrimitive.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,eAAe,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ToastPrimitive.d.ts","sourceRoot":"","sources":["../../../src/atomic/Toaster/ToastPrimitive.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,eAAe,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1D,QAAA,MAAM,aAAa,wDAA2B,CAAC;AAE/C,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,eAAe,CAAC,QAAQ,CAAC,2CAOjD;AAED,QAAA,MAAM,aAAa;;8EAajB,CAAC;AAEH,UAAU,UACR,SACE,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,EAC3C,YAAY,CAAC,OAAO,aAAa,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,KAAK,kBAAkB,GAAG,YAAY,CAAC,OAAO,WAAW,CAAC,CAAC;AAE3D,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,2CA6BrE;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,eAAe,CAAC,MAAM,CAAC,2CAQ/C;AAED,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAyB9C;AAED,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAO9C;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,eAAe,CAAC,WAAW,CAAC,2CAOpD;AAED,eAAe,KAAK,CAAC;AACrB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,aAAa,EACb,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,WAAW,GACZ,CAAC"}
|
|
@@ -97,7 +97,17 @@ export interface VideoPlayerProps {
|
|
|
97
97
|
* @default true
|
|
98
98
|
*/
|
|
99
99
|
allowFullscreen?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Aria label for the play button/thumbnail
|
|
102
|
+
* @default 'Click to watch video'
|
|
103
|
+
*/
|
|
104
|
+
playButtonLabel?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Aria label for loading state
|
|
107
|
+
* @default 'Loading video'
|
|
108
|
+
*/
|
|
109
|
+
loadingLabel?: string;
|
|
100
110
|
}
|
|
101
|
-
declare const VideoPlayer: ({ url, trigger, thumbnail, eager, title, modal, aspectRatio, className, autoplay, allowFullscreen, }: VideoPlayerProps) => import("react/jsx-runtime").JSX.Element;
|
|
111
|
+
declare const VideoPlayer: ({ url, trigger, thumbnail, eager, title, modal, aspectRatio, className, autoplay, allowFullscreen, playButtonLabel, loadingLabel, }: VideoPlayerProps) => import("react/jsx-runtime").JSX.Element;
|
|
102
112
|
export default VideoPlayer;
|
|
103
113
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/VideoPlayer/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/VideoPlayer/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,qBAAqB;IACrB,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,eAAe;IACf,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,qFAAqF;IACrF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA4JD,QAAA,MAAM,WAAW,GAAI,qIAalB,gBAAgB,4CAuJlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -9,9 +9,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
* @author AMBROISE PARK Consulting
|
|
10
10
|
*/
|
|
11
11
|
import { Play } from 'lucide-react';
|
|
12
|
-
import { useState, useEffect
|
|
13
|
-
import { useIntersectionObserver } from '
|
|
14
|
-
import { useTranslation } from '@donotdev/core';
|
|
12
|
+
import { useState, useEffect } from 'react';
|
|
13
|
+
import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
|
|
15
14
|
import { cn } from '../../utils/helpers';
|
|
16
15
|
import Button, { BUTTON_VARIANT } from '../Button';
|
|
17
16
|
import Dialog from '../Dialog';
|
|
@@ -139,8 +138,7 @@ const getThumbnailUrl = (urlOrConfig) => {
|
|
|
139
138
|
* Lazy-loads actual thumbnail on intersection
|
|
140
139
|
*/
|
|
141
140
|
const VideoPlaceholder = ({ aspectRatio, className, }) => (_jsxs("svg", { className: cn('dndev-video-placeholder', className), viewBox: "0 0 16 9", style: { aspectRatio, width: '100%', display: 'block' }, preserveAspectRatio: "xMidYMid meet", "aria-hidden": "true", children: [_jsx("rect", { width: "16", height: "9", fill: "var(--muted)" }), _jsx("circle", { cx: "8", cy: "4.5", r: "1.5", fill: "var(--foreground)", opacity: "0.8" }), _jsx("path", { d: "M7 3.5L7 5.5L9 4.5Z", fill: "var(--background)" })] }));
|
|
142
|
-
const VideoPlayer = ({ url = { platform: 'youtube', id: 'dQw4w9WgXcQ' }, trigger, thumbnail, eager = false, title = 'Video', modal = true, aspectRatio = '16/9', className, autoplay = false, allowFullscreen = true, }) => {
|
|
143
|
-
const { t } = useTranslation(['dndev']);
|
|
141
|
+
const VideoPlayer = ({ url = { platform: 'youtube', id: 'dQw4w9WgXcQ' }, trigger, thumbnail, eager = false, title = 'Video', modal = true, aspectRatio = '16/9', className, autoplay = false, allowFullscreen = true, playButtonLabel = 'Click to watch video', loadingLabel = 'Loading video', }) => {
|
|
144
142
|
const [isOpen, setIsOpen] = useState(false);
|
|
145
143
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
146
144
|
const [iframeReady, setIframeReady] = useState(false);
|
|
@@ -176,17 +174,17 @@ const VideoPlayer = ({ url = { platform: 'youtube', id: 'dQw4w9WgXcQ' }, trigger
|
|
|
176
174
|
e.preventDefault();
|
|
177
175
|
setIsLoaded(true);
|
|
178
176
|
}
|
|
179
|
-
}, className: cn('dndev-video-thumbnail', className), style: { aspectRatio }, "aria-label":
|
|
177
|
+
}, className: cn('dndev-video-thumbnail', className), style: { aspectRatio }, "aria-label": playButtonLabel, children: [thumbnailLoaded && thumbnailUrl ? (_jsx("img", { src: thumbnailUrl, alt: title, loading: "eager", fetchPriority: "high", decoding: "async" })) : (_jsx(VideoPlaceholder, { aspectRatio: aspectRatio })), _jsx("div", { className: "dndev-video-play-overlay", children: _jsx(Play, { className: "dndev-video-play-icon" }) })] }));
|
|
180
178
|
}
|
|
181
179
|
// Clicked - show iframe with thumbnail overlay until iframe loads
|
|
182
180
|
return (_jsxs("div", { className: cn('dndev-video-container', className), style: { aspectRatio, position: 'relative' }, children: [videoFrame, !iframeReady && thumbnailUrl && (_jsxs("div", { className: "dndev-video-thumbnail dndev-video-loading-overlay", style: {
|
|
183
181
|
position: 'absolute',
|
|
184
182
|
inset: 0,
|
|
185
183
|
pointerEvents: 'none',
|
|
186
|
-
}, children: [_jsx("img", { src: thumbnailUrl, alt: title, loading: "eager", decoding: "async" }), _jsx("div", { className: "dndev-video-play-overlay dndev-video-loading", children: _jsx(Spinner, { "aria-label":
|
|
184
|
+
}, children: [_jsx("img", { src: thumbnailUrl, alt: title, loading: "eager", decoding: "async" }), _jsx("div", { className: "dndev-video-play-overlay dndev-video-loading", children: _jsx(Spinner, { "aria-label": loadingLabel }) })] }))] }));
|
|
187
185
|
}
|
|
188
186
|
// Modal mode - lazy-load iframe when modal opens
|
|
189
|
-
const defaultTrigger = (_jsxs("button", { ref: thumbnailRef, type: "button", className: "dndev-video-thumbnail", style: { aspectRatio }, "aria-label":
|
|
187
|
+
const defaultTrigger = (_jsxs("button", { ref: thumbnailRef, type: "button", className: "dndev-video-thumbnail", style: { aspectRatio }, "aria-label": playButtonLabel, children: [thumbnailLoaded && thumbnailUrl ? (_jsx("img", { src: thumbnailUrl, alt: title, loading: "eager", fetchPriority: "high", decoding: "async" })) : (_jsx(VideoPlaceholder, { aspectRatio: aspectRatio })), _jsx("div", { className: "dndev-video-play-overlay", children: _jsx(Play, { className: "dndev-video-play-icon" }) })] }));
|
|
190
188
|
return (_jsx(Dialog, { trigger: trigger || defaultTrigger, title: title, open: isOpen, onOpenChange: setIsOpen, showClose: true, className: "dndev-video-dialog", children: videoFrame }));
|
|
191
189
|
};
|
|
192
190
|
export default VideoPlayer;
|
package/dist/atomic/index.d.ts
CHANGED
|
@@ -105,6 +105,8 @@ export type { ProgressProps } from './Progress';
|
|
|
105
105
|
export { default as RadioGroup } from './RadioGroup';
|
|
106
106
|
export * from './RadioGroup/RadioGroupPrimitive';
|
|
107
107
|
export type { RadioOption, RadioGroupProps, RadioGroupVariant, } from './RadioGroup';
|
|
108
|
+
export { default as RangeInput } from './RangeInput';
|
|
109
|
+
export type { RangeInputProps } from './RangeInput';
|
|
108
110
|
export { default as ScrollArea, ScrollBar } from './ScrollArea';
|
|
109
111
|
export * from './ScrollArea/ScrollAreaPrimitive';
|
|
110
112
|
export type { ScrollAreaProps, ScrollBarProps } from './ScrollArea';
|