@design-edito/tools 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agnostic/html/deep-select/index.js +5 -3
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.d.ts +8 -8
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.js +8 -8
- package/agnostic/html/hyper-json/smart-tags/isolated/index.d.ts +2 -2
- package/agnostic/html/hyper-json/smart-tags/isolated/index.js +2 -2
- package/agnostic/html/index.d.ts +1 -1
- package/agnostic/html/index.js +1 -1
- package/agnostic/misc/index.d.ts +3 -3
- package/agnostic/misc/index.js +3 -3
- package/agnostic/numbers/index.d.ts +1 -1
- package/agnostic/numbers/index.js +1 -1
- package/agnostic/optim/index.d.ts +1 -1
- package/agnostic/optim/index.js +1 -1
- package/agnostic/strings/index.d.ts +1 -1
- package/agnostic/strings/index.js +1 -1
- package/agnostic/time/dates/format-date/index.d.ts +4 -2
- package/agnostic/time/dates/format-date/index.js +43 -94
- package/agnostic/time/dates/format-date/index.test.js +154 -0
- package/agnostic/time/dates/format-date/parts.d.ts +28 -0
- package/agnostic/time/dates/format-date/parts.js +136 -0
- package/agnostic/time/dates/format-date/types.d.ts +84 -0
- package/agnostic/time/dates/format-date/types.js +1 -0
- package/agnostic/time/duration/format-duration/index.d.ts +42 -0
- package/agnostic/time/duration/format-duration/index.js +94 -0
- package/agnostic/time/duration/format-duration/index.test.d.ts +1 -0
- package/agnostic/time/duration/format-duration/index.test.js +148 -0
- package/agnostic/time/duration/format-duration/parts.d.ts +32 -0
- package/agnostic/time/duration/format-duration/parts.js +107 -0
- package/agnostic/time/duration/format-duration/types.d.ts +93 -0
- package/agnostic/time/duration/format-duration/types.js +1 -0
- package/agnostic/time/duration/index.d.ts +6 -1
- package/agnostic/time/duration/index.js +2 -2
- package/agnostic/time/duration/index.test.d.ts +1 -0
- package/agnostic/time/duration/index.test.js +168 -0
- package/agnostic/time/index.d.ts +1 -1
- package/agnostic/time/index.js +1 -1
- package/components/BeforeAfter/index.controlled.d.ts +25 -25
- package/components/BeforeAfter/index.controlled.js +47 -53
- package/components/BeforeAfter/index.d.ts +20 -23
- package/components/BeforeAfter/index.js +48 -40
- package/components/Button/index.js +1 -1
- package/components/Clippable/index.d.ts +17 -26
- package/components/Clippable/index.js +21 -23
- package/components/Disclaimer/index.d.ts +29 -22
- package/components/Disclaimer/index.js +29 -24
- package/components/Drawer/index.d.ts +45 -25
- package/components/Drawer/index.js +61 -52
- package/components/EventListener/index.d.ts +4 -5
- package/components/Gallery/index.d.ts +14 -16
- package/components/Gallery/index.js +25 -30
- package/components/Iframe/index.js +2 -2
- package/components/Image/index.d.ts +5 -12
- package/components/Image/index.js +11 -32
- package/components/Input/index.d.ts +23 -19
- package/components/Input/index.js +30 -20
- package/components/JsonEditor/index.d.ts +177 -9
- package/components/JsonEditor/index.js +133 -77
- package/components/JsonEditor/types.d.ts +11 -0
- package/components/JsonEditor/types.js +1 -0
- package/components/JsonEditor/utils.d.ts +8 -0
- package/components/JsonEditor/utils.js +23 -0
- package/components/ListLoader/index.controlled.d.ts +5 -5
- package/components/ListLoader/index.controlled.js +4 -4
- package/components/ListLoader/index.d.ts +11 -11
- package/components/ListLoader/index.js +12 -12
- package/components/Overlayer/index.js +4 -4
- package/components/Paginator/index.d.ts +7 -12
- package/components/Paginator/index.js +7 -11
- package/components/ResizeObserver/index.d.ts +14 -3
- package/components/ResizeObserver/index.js +49 -24
- package/components/Scrllgngn/index.d.ts +17 -13
- package/components/Scrllgngn/index.js +25 -84
- package/components/Scrllgngn/utils.d.ts +52 -0
- package/components/Scrllgngn/utils.js +102 -0
- package/components/ScrollListener/index.d.ts +43 -28
- package/components/ScrollListener/index.js +59 -79
- package/components/ScrollListener/utils.d.ts +37 -16
- package/components/ScrollListener/utils.js +141 -28
- package/components/Select/index.d.ts +24 -20
- package/components/Select/index.js +30 -20
- package/components/Sequencer/index.controlled.d.ts +16 -26
- package/components/Sequencer/index.controlled.js +15 -12
- package/components/Sequencer/index.d.ts +25 -30
- package/components/Sequencer/index.js +20 -34
- package/components/Subtitles/index.d.ts +29 -5
- package/components/Subtitles/index.js +90 -12
- package/components/Textarea/index.d.ts +26 -20
- package/components/Textarea/index.js +40 -21
- package/components/Theatre/index.d.ts +35 -39
- package/components/Theatre/index.js +46 -58
- package/components/UIModule/index.d.ts +25 -29
- package/components/UIModule/index.js +81 -110
- package/components/Video/index.controlled.d.ts +51 -51
- package/components/Video/index.controlled.js +75 -72
- package/components/Video/index.d.ts +12 -14
- package/components/Video/index.js +41 -86
- package/components/Video/utils.d.ts +35 -3
- package/components/Video/utils.js +37 -14
- package/components/index.d.ts +1 -1
- package/components/index.js +1 -1
- package/components/utils/index.d.ts +22 -0
- package/components/utils/index.js +31 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/node/@aws-s3/storage/file/index.d.ts +1 -1
- package/node/@aws-s3/storage/file/index.js +1 -1
- package/node/@google-cloud/storage/index.d.ts +1 -1
- package/node/@google-cloud/storage/index.js +1 -1
- package/node/images/index.d.ts +1 -1
- package/node/images/index.js +1 -1
- package/node/images/transform/operations/index.d.ts +1 -1
- package/node/images/transform/operations/index.js +1 -1
- package/node/index.d.ts +1 -1
- package/node/index.js +1 -1
- package/package.json +20 -5
- package/TODO.md +0 -269
- package/components/BeforeAfter/utils.d.ts +0 -4
- package/components/BeforeAfter/utils.js +0 -9
- package/components/Input/index.controlled.d.ts +0 -42
- package/components/Input/index.controlled.js +0 -54
- package/components/Select/index.controlled.d.ts +0 -43
- package/components/Select/index.controlled.js +0 -54
- package/components/Subtitles/types.d.ts +0 -24
- package/components/Subtitles/utils.d.ts +0 -32
- package/components/Subtitles/utils.js +0 -107
- package/components/Textarea/index.controlled.d.ts +0 -50
- package/components/Textarea/index.controlled.js +0 -75
- /package/{components/Subtitles/types.js → agnostic/time/dates/format-date/index.test.d.ts} +0 -0
- /package/components/ResizeObserver/{style.module.css → styles.module.css} +0 -0
|
@@ -1,54 +1,62 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { useChangeDispatch } from '../utils/index.js';
|
|
4
|
+
import { ControlledBeforeAfter } from './index.controlled.js';
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
* Pointer ratios are stretched by this much on each side before becoming the
|
|
7
|
+
* divider position, so the very edges stay reachable without having to land the
|
|
8
|
+
* pointer exactly on the component's border.
|
|
9
|
+
*/
|
|
10
|
+
const edgeOvershoot = 0.01;
|
|
11
|
+
/** Turns a raw pointer ratio into a divider position, edges included. */
|
|
12
|
+
function toDividerRatio(pointerRatio) {
|
|
13
|
+
return pointerRatio * (1 + 2 * edgeOvershoot) - edgeOvershoot;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Before/after comparison component supporting controlled and uncontrolled usage.
|
|
11
17
|
*
|
|
12
|
-
* @
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* - In uncontrolled mode, internal state is initialized from `defaultRatio` and updated
|
|
16
|
-
* on both drag and click interactions.
|
|
17
|
-
* - `actionHandlers.dragged` and `actionHandlers.clicked` are always forwarded to the
|
|
18
|
-
* underlying controlled component, regardless of mode.
|
|
18
|
+
* Turns the pointer ratios reported by {@link ControlledBeforeAfter} into a
|
|
19
|
+
* divider position, reading the axis that matches `mode`: the x ratio when
|
|
20
|
+
* horizontal, the y ratio when vertical.
|
|
19
21
|
*
|
|
20
22
|
* @param props - Component properties.
|
|
21
23
|
* @see {@link Props}
|
|
22
|
-
* @
|
|
24
|
+
* @see {@link ControlledBeforeAfter} for the rendered markup and CSS elements.
|
|
25
|
+
* @returns A {@link ControlledBeforeAfter} with the divider position managed
|
|
26
|
+
* internally when uncontrolled.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* - In controlled mode (`ratio` defined), the divider position is fully driven
|
|
30
|
+
* by the parent and internal state is never updated.
|
|
31
|
+
* - `onDragged` and `onClicked` fire in both modes — a controlled parent needs
|
|
32
|
+
* them to know where the pointer went.
|
|
33
|
+
* - `onRatioChanged` fires in both modes too, and never on mount.
|
|
23
34
|
*/
|
|
24
|
-
export const BeforeAfter = ({ mode = 'horizontal',
|
|
35
|
+
export const BeforeAfter = ({ mode = 'horizontal', ratio, defaultRatio = 0.5, onDragged, onClicked, onRatioChanged, ...controlledProps }) => {
|
|
36
|
+
// State
|
|
25
37
|
const [internalRatio, setInternalRatio] = useState(defaultRatio);
|
|
26
38
|
const isControlled = ratio !== undefined;
|
|
27
39
|
const effectiveRatio = isControlled ? ratio : internalRatio;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
// State dispatch
|
|
41
|
+
useChangeDispatch(effectiveRatio, onRatioChanged);
|
|
42
|
+
// User action handlers
|
|
43
|
+
const moveDividerTo = (xRatio, yRatio) => {
|
|
44
|
+
if (isControlled)
|
|
45
|
+
return;
|
|
46
|
+
setInternalRatio(mode === 'horizontal' ? xRatio : yRatio);
|
|
47
|
+
};
|
|
48
|
+
const handleDrag = (xRatio, yRatio) => {
|
|
49
|
+
const x = toDividerRatio(xRatio);
|
|
50
|
+
const y = toDividerRatio(yRatio);
|
|
51
|
+
onDragged?.(x, y);
|
|
52
|
+
moveDividerTo(x, y);
|
|
38
53
|
};
|
|
39
|
-
const handleClick = (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
actionHandlers?.clicked?.(x, y);
|
|
45
|
-
if (!isControlled) {
|
|
46
|
-
setInternalRatio(mode === 'horizontal' ? x : y);
|
|
47
|
-
stateHandlers?.ratioChanged?.(mode === 'horizontal' ? x : y);
|
|
48
|
-
}
|
|
54
|
+
const handleClick = (xRatio, yRatio) => {
|
|
55
|
+
const x = toDividerRatio(xRatio);
|
|
56
|
+
const y = toDividerRatio(yRatio);
|
|
57
|
+
onClicked?.(x, y);
|
|
58
|
+
moveDividerTo(x, y);
|
|
49
59
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
clicked: handleClick
|
|
53
|
-
} });
|
|
60
|
+
// Rendering
|
|
61
|
+
return _jsx(ControlledBeforeAfter, { ...controlledProps, mode: mode, ratio: effectiveRatio, onDragged: handleDrag, onClicked: handleClick });
|
|
54
62
|
};
|
|
@@ -15,6 +15,6 @@ import cssModule from './styles.module.css';
|
|
|
15
15
|
*/
|
|
16
16
|
export const Button = ({ className, ...rest }) => {
|
|
17
17
|
const c = clss(publicClassName, { cssModule });
|
|
18
|
-
const rootClss = mergeClassNames(c(
|
|
18
|
+
const rootClss = mergeClassNames(c(), className);
|
|
19
19
|
return _jsx("button", { ...rest, className: rootClss });
|
|
20
20
|
};
|
|
@@ -3,40 +3,27 @@ import type { WithClassName } from '../utils/types.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Props for the {@link Clippable} component.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @property
|
|
12
|
-
*
|
|
13
|
-
* @property stateHandlers - Optional callbacks invoked when derived state changes:
|
|
14
|
-
* - `clipped` — called after content has been successfully written to the clipboard.
|
|
6
|
+
* @property toClip - Content written to the clipboard. When omitted, the
|
|
7
|
+
* content container's `innerHTML` is used. A function may be provided to
|
|
8
|
+
* transform that current content before it is written.
|
|
9
|
+
* @property onCopyClicked - Called when the copy button is clicked, before the
|
|
10
|
+
* clipboard content is resolved, with the container's raw HTML.
|
|
11
|
+
* @property onClipped - Called once content has been written to the clipboard.
|
|
12
|
+
* Not called when the write fails.
|
|
15
13
|
* @property className - Additional class name(s) applied to the root element.
|
|
16
14
|
* @property children - Content rendered inside the copyable container.
|
|
17
15
|
*/
|
|
18
16
|
export type Props = PropsWithChildren<WithClassName<{
|
|
19
17
|
toClip?: string | ((curr: string | undefined) => string | undefined);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
};
|
|
23
|
-
stateHandlers?: {
|
|
24
|
-
clipped?: (content: string) => void;
|
|
25
|
-
};
|
|
18
|
+
onCopyClicked?: (e: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>, rawContent: string | undefined) => void;
|
|
19
|
+
onClipped?: (content: string) => void;
|
|
26
20
|
}>>;
|
|
27
21
|
/**
|
|
28
|
-
* Clipboard-enabled container
|
|
29
|
-
*
|
|
30
|
-
* Renders arbitrary content alongside a copy control. When activated,
|
|
31
|
-
* the component writes HTML content to the clipboard using the
|
|
32
|
-
* `text/html` MIME type.
|
|
33
|
-
*
|
|
34
|
-
* Supports content overriding and transformation through the `toClip`
|
|
35
|
-
* prop, as well as action and state callbacks.
|
|
22
|
+
* Clipboard-enabled container. Renders arbitrary content alongside a copy
|
|
23
|
+
* control that writes it to the clipboard, as both `text/html` and `text/plain`.
|
|
36
24
|
*
|
|
37
25
|
* ### CSS modifiers
|
|
38
|
-
*
|
|
39
|
-
* - `clipped` — `true` during the 3 seconds following a successful clipboard write.
|
|
26
|
+
* - `clipped` — on during the 3 seconds following a successful write.
|
|
40
27
|
*
|
|
41
28
|
* ### CSS elements
|
|
42
29
|
* - `copy`
|
|
@@ -44,6 +31,10 @@ export type Props = PropsWithChildren<WithClassName<{
|
|
|
44
31
|
*
|
|
45
32
|
* @param props - Component properties.
|
|
46
33
|
* @see {@link Props}
|
|
47
|
-
* @returns A copy-enabled content container
|
|
34
|
+
* @returns A copy-enabled content container.
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* A failed clipboard write is logged and leaves the component untouched:
|
|
38
|
+
* neither `onClipped` nor the `clipped` modifier fires.
|
|
48
39
|
*/
|
|
49
40
|
export declare const Clippable: FunctionComponent<Props>;
|
|
@@ -4,19 +4,14 @@ import { clss } from '../../agnostic/css/clss/index.js';
|
|
|
4
4
|
import { mergeClassNames } from '../utils/index.js';
|
|
5
5
|
import { clippable as publicClassName } from '../public-classnames.js';
|
|
6
6
|
import cssModule from './styles.module.css';
|
|
7
|
+
/** How long the `clipped` modifier stays on after a successful write. */
|
|
8
|
+
const clippedModifierDurationMs = 3000;
|
|
7
9
|
/**
|
|
8
|
-
* Clipboard-enabled container
|
|
9
|
-
*
|
|
10
|
-
* Renders arbitrary content alongside a copy control. When activated,
|
|
11
|
-
* the component writes HTML content to the clipboard using the
|
|
12
|
-
* `text/html` MIME type.
|
|
13
|
-
*
|
|
14
|
-
* Supports content overriding and transformation through the `toClip`
|
|
15
|
-
* prop, as well as action and state callbacks.
|
|
10
|
+
* Clipboard-enabled container. Renders arbitrary content alongside a copy
|
|
11
|
+
* control that writes it to the clipboard, as both `text/html` and `text/plain`.
|
|
16
12
|
*
|
|
17
13
|
* ### CSS modifiers
|
|
18
|
-
*
|
|
19
|
-
* - `clipped` — `true` during the 3 seconds following a successful clipboard write.
|
|
14
|
+
* - `clipped` — on during the 3 seconds following a successful write.
|
|
20
15
|
*
|
|
21
16
|
* ### CSS elements
|
|
22
17
|
* - `copy`
|
|
@@ -24,22 +19,26 @@ import cssModule from './styles.module.css';
|
|
|
24
19
|
*
|
|
25
20
|
* @param props - Component properties.
|
|
26
21
|
* @see {@link Props}
|
|
27
|
-
* @returns A copy-enabled content container
|
|
22
|
+
* @returns A copy-enabled content container.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* A failed clipboard write is logged and leaves the component untouched:
|
|
26
|
+
* neither `onClipped` nor the `clipped` modifier fires.
|
|
28
27
|
*/
|
|
29
|
-
export const Clippable = ({ className, children, toClip,
|
|
28
|
+
export const Clippable = ({ className, children, toClip, onCopyClicked, onClipped }) => {
|
|
30
29
|
// State & refs
|
|
31
|
-
const [
|
|
30
|
+
const [hasBeenRecentlyClipped, setHasBeenRecentlyClipped] = useState(false);
|
|
32
31
|
const contentRef = useRef(null);
|
|
33
32
|
const clippedTimeoutRef = useRef(null);
|
|
34
33
|
// User action handlers
|
|
35
34
|
const handleCopyClick = async (e) => {
|
|
36
|
-
const
|
|
37
|
-
|
|
35
|
+
const rawHtml = contentRef.current?.innerHTML;
|
|
36
|
+
onCopyClicked?.(e, rawHtml);
|
|
38
37
|
const html = typeof toClip === 'string'
|
|
39
38
|
? toClip
|
|
40
39
|
: typeof toClip === 'function'
|
|
41
|
-
? toClip(
|
|
42
|
-
:
|
|
40
|
+
? toClip(rawHtml)
|
|
41
|
+
: rawHtml;
|
|
43
42
|
if (html === undefined)
|
|
44
43
|
return;
|
|
45
44
|
try {
|
|
@@ -53,19 +52,18 @@ export const Clippable = ({ className, children, toClip, actionHandlers, stateHa
|
|
|
53
52
|
catch (err) {
|
|
54
53
|
// eslint-disable-next-line no-console
|
|
55
54
|
console.error(err);
|
|
55
|
+
return;
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
onClipped?.(html);
|
|
58
|
+
setHasBeenRecentlyClipped(true);
|
|
59
59
|
if (clippedTimeoutRef.current !== null)
|
|
60
60
|
clearTimeout(clippedTimeoutRef.current);
|
|
61
|
-
clippedTimeoutRef.current = setTimeout(() =>
|
|
62
|
-
setBeenRecentlyClipped(false);
|
|
63
|
-
}, 3000);
|
|
61
|
+
clippedTimeoutRef.current = setTimeout(() => setHasBeenRecentlyClipped(false), clippedModifierDurationMs);
|
|
64
62
|
};
|
|
65
63
|
// Rendering
|
|
66
64
|
const c = clss(publicClassName, { cssModule });
|
|
67
65
|
const rootClss = mergeClassNames(c(null, {
|
|
68
|
-
clipped:
|
|
66
|
+
clipped: hasBeenRecentlyClipped
|
|
69
67
|
}), className);
|
|
70
68
|
const copyClss = c('copy');
|
|
71
69
|
const contentClss = c('content');
|
|
@@ -1,45 +1,52 @@
|
|
|
1
1
|
import { type ReactNode, type PropsWithChildren, type FunctionComponent } from 'react';
|
|
2
2
|
import type { WithClassName } from '../utils/types.js';
|
|
3
3
|
/**
|
|
4
|
-
* Props for the Disclaimer component.
|
|
4
|
+
* Props for the {@link Disclaimer} component.
|
|
5
5
|
*
|
|
6
6
|
* @property content - Content displayed inside the disclaimer panel.
|
|
7
7
|
* @property togglerContent - Content rendered inside the dismiss toggler.
|
|
8
|
-
*
|
|
9
|
-
* @property isOn -
|
|
10
|
-
* behaves as a controlled component.
|
|
11
|
-
* @property defaultIsOn -
|
|
12
|
-
*
|
|
13
|
-
* @property
|
|
14
|
-
*
|
|
15
|
-
* @property
|
|
8
|
+
* When omitted, the toggler is not rendered.
|
|
9
|
+
* @property isOn - Controlled visibility state. When defined, the component
|
|
10
|
+
* behaves as a controlled component and internal state is never updated.
|
|
11
|
+
* @property defaultIsOn - Initial visibility state in uncontrolled mode.
|
|
12
|
+
* Ignored when `isOn` is provided. Defaults to `true`.
|
|
13
|
+
* @property onDismissClicked - Called when the toggler is clicked, before the
|
|
14
|
+
* disclaimer reacts, with the visibility state as it was.
|
|
15
|
+
* @property onIsOnChanged - Called after the visibility state changed, with the
|
|
16
|
+
* new value.
|
|
16
17
|
* @property className - Optional additional class name(s) applied to the root element.
|
|
17
|
-
* @property children -
|
|
18
|
+
* @property children - The content the disclaimer gates, rendered below the panel.
|
|
18
19
|
*/
|
|
19
20
|
export type Props = PropsWithChildren<WithClassName<{
|
|
20
21
|
content?: ReactNode;
|
|
21
22
|
togglerContent?: ReactNode;
|
|
22
23
|
isOn?: boolean;
|
|
23
24
|
defaultIsOn?: boolean;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
actionHandlers?: {
|
|
28
|
-
dismissClick?: (prevIsOn: boolean) => void;
|
|
29
|
-
};
|
|
25
|
+
onDismissClicked?: (isOn: boolean) => void;
|
|
26
|
+
onIsOnChanged?: (isOn: boolean) => void;
|
|
30
27
|
}>>;
|
|
31
28
|
/**
|
|
32
|
-
*
|
|
29
|
+
* Dismissible disclaimer panel, gating the content it wraps.
|
|
33
30
|
*
|
|
34
|
-
*
|
|
31
|
+
* ### CSS modifiers
|
|
32
|
+
* - `on` — the disclaimer is showing.
|
|
33
|
+
* - `off` — the disclaimer has been dismissed.
|
|
34
|
+
*
|
|
35
|
+
* ### CSS elements
|
|
36
|
+
* - `panel`
|
|
37
|
+
* - `content`
|
|
38
|
+
* - `toggler`
|
|
39
|
+
* - `sensitive` — wraps `children`.
|
|
35
40
|
*
|
|
36
41
|
* @param props - Component properties.
|
|
37
42
|
* @see {@link Props}
|
|
43
|
+
* @returns A root `<div>` holding the disclaimer panel and the gated content.
|
|
38
44
|
*
|
|
39
45
|
* @remarks
|
|
40
|
-
* - In controlled mode, visibility is driven by
|
|
41
|
-
*
|
|
42
|
-
* -
|
|
43
|
-
*
|
|
46
|
+
* - In controlled mode (`isOn` defined), visibility is fully driven by the
|
|
47
|
+
* parent and internal state is never updated.
|
|
48
|
+
* - `onDismissClicked` fires in both modes — a controlled parent needs it to
|
|
49
|
+
* know a click happened at all.
|
|
50
|
+
* - `onIsOnChanged` fires in both modes too, and never on mount.
|
|
44
51
|
*/
|
|
45
52
|
export declare const Disclaimer: FunctionComponent<Props>;
|
|
@@ -1,39 +1,44 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState
|
|
2
|
+
import { useState } from 'react';
|
|
3
3
|
import { clss } from '../../agnostic/css/clss/index.js';
|
|
4
|
-
import { mergeClassNames } from '../utils/index.js';
|
|
4
|
+
import { mergeClassNames, useChangeDispatch } from '../utils/index.js';
|
|
5
5
|
import { disclaimer as publicClassName } from '../public-classnames.js';
|
|
6
6
|
import cssModule from './styles.module.css';
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Dismissible disclaimer panel, gating the content it wraps.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* ### CSS modifiers
|
|
11
|
+
* - `on` — the disclaimer is showing.
|
|
12
|
+
* - `off` — the disclaimer has been dismissed.
|
|
13
|
+
*
|
|
14
|
+
* ### CSS elements
|
|
15
|
+
* - `panel`
|
|
16
|
+
* - `content`
|
|
17
|
+
* - `toggler`
|
|
18
|
+
* - `sensitive` — wraps `children`.
|
|
11
19
|
*
|
|
12
20
|
* @param props - Component properties.
|
|
13
21
|
* @see {@link Props}
|
|
22
|
+
* @returns A root `<div>` holding the disclaimer panel and the gated content.
|
|
14
23
|
*
|
|
15
24
|
* @remarks
|
|
16
|
-
* - In controlled mode, visibility is driven by
|
|
17
|
-
*
|
|
18
|
-
* -
|
|
19
|
-
*
|
|
25
|
+
* - In controlled mode (`isOn` defined), visibility is fully driven by the
|
|
26
|
+
* parent and internal state is never updated.
|
|
27
|
+
* - `onDismissClicked` fires in both modes — a controlled parent needs it to
|
|
28
|
+
* know a click happened at all.
|
|
29
|
+
* - `onIsOnChanged` fires in both modes too, and never on mount.
|
|
20
30
|
*/
|
|
21
|
-
export const Disclaimer = ({ content, togglerContent, isOn: isOnProp, defaultIsOn
|
|
22
|
-
// State
|
|
23
|
-
const [internalIsOn, setInternalIsOn] = useState(
|
|
31
|
+
export const Disclaimer = ({ content, togglerContent, isOn: isOnProp, defaultIsOn = true, onDismissClicked, onIsOnChanged, children, className }) => {
|
|
32
|
+
// State
|
|
33
|
+
const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);
|
|
34
|
+
const isControlled = isOnProp !== undefined;
|
|
24
35
|
const isOn = isOnProp ?? internalIsOn;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (pIsOn.current === isOn)
|
|
29
|
-
return;
|
|
30
|
-
stateHandlers?.toggled?.(isOn);
|
|
31
|
-
pIsOn.current = isOn;
|
|
32
|
-
}, [isOn]);
|
|
33
|
-
// User actions handlers
|
|
36
|
+
// State dispatch
|
|
37
|
+
useChangeDispatch(isOn, onIsOnChanged);
|
|
38
|
+
// User action handlers
|
|
34
39
|
const handleDismissClick = () => {
|
|
35
|
-
|
|
36
|
-
if (
|
|
40
|
+
onDismissClicked?.(isOn);
|
|
41
|
+
if (isControlled)
|
|
37
42
|
return;
|
|
38
43
|
setInternalIsOn(false);
|
|
39
44
|
};
|
|
@@ -45,7 +50,7 @@ export const Disclaimer = ({ content, togglerContent, isOn: isOnProp, defaultIsO
|
|
|
45
50
|
}), className);
|
|
46
51
|
const panelClss = c('panel');
|
|
47
52
|
const contentClss = c('content');
|
|
48
|
-
const
|
|
53
|
+
const togglerClss = c('toggler');
|
|
49
54
|
const sensitiveClss = c('sensitive');
|
|
50
|
-
return _jsxs("div", { className: rootClss, children: [_jsxs("div", { className: panelClss, children: [content !== undefined && _jsx("div", { className: contentClss, children: content }), togglerContent !== undefined && _jsx("div", { className:
|
|
55
|
+
return _jsxs("div", { className: rootClss, children: [_jsxs("div", { className: panelClss, children: [content !== undefined && _jsx("div", { className: contentClss, children: content }), togglerContent !== undefined && _jsx("div", { className: togglerClss, onClick: handleDismissClick, children: togglerContent })] }), _jsx("div", { className: sensitiveClss, children: children })] });
|
|
51
56
|
};
|
|
@@ -1,45 +1,65 @@
|
|
|
1
1
|
import { type PropsWithChildren, type FunctionComponent, type ReactNode } from 'react';
|
|
2
2
|
import type { WithClassName } from '../utils/types.js';
|
|
3
3
|
/**
|
|
4
|
-
* Props for the Drawer component.
|
|
4
|
+
* Props for the {@link Drawer} component.
|
|
5
5
|
*
|
|
6
6
|
* @property openerContent - Content rendered inside the opener control.
|
|
7
7
|
* @property closerContent - Content rendered inside the closer control.
|
|
8
|
-
* @property
|
|
9
|
-
* Ignored when `isOpened` is provided.
|
|
8
|
+
* @property defaultIsOpened - Initial open state in uncontrolled mode.
|
|
9
|
+
* Ignored when `isOpened` is provided. Defaults to `false`.
|
|
10
10
|
* @property isOpened - Controlled open state. When defined, the component
|
|
11
|
-
* behaves as a controlled component and internal state is
|
|
12
|
-
* @property
|
|
13
|
-
*
|
|
11
|
+
* behaves as a controlled component and internal state is never updated.
|
|
12
|
+
* @property onOpenerClicked - Called when the opener is clicked, before the
|
|
13
|
+
* drawer reacts, with the open state as it was.
|
|
14
|
+
* @property onCloserClicked - Called when the closer is clicked, before the
|
|
15
|
+
* drawer reacts, with the open state as it was.
|
|
16
|
+
* @property onIsOpenedChanged - Called after the open state changed, with the
|
|
17
|
+
* new value.
|
|
14
18
|
* @property className - Additional class name(s) applied to the root element.
|
|
15
19
|
* @property children - Drawer content.
|
|
16
20
|
*/
|
|
17
21
|
export type Props = PropsWithChildren<WithClassName<{
|
|
18
22
|
openerContent?: ReactNode;
|
|
19
23
|
closerContent?: ReactNode;
|
|
20
|
-
|
|
24
|
+
defaultIsOpened?: boolean;
|
|
21
25
|
isOpened?: boolean;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
onOpenerClicked?: (isOpened: boolean) => void;
|
|
27
|
+
onCloserClicked?: (isOpened: boolean) => void;
|
|
28
|
+
onIsOpenedChanged?: (isOpened: boolean) => void;
|
|
25
29
|
}>>;
|
|
26
30
|
/**
|
|
27
|
-
* Drawer component
|
|
31
|
+
* Drawer component supporting controlled and uncontrolled usage.
|
|
32
|
+
*
|
|
33
|
+
* The content is measured through a {@link ResizeObserverComponent} so its
|
|
34
|
+
* dimensions can drive the open/close transition from CSS alone.
|
|
35
|
+
*
|
|
36
|
+
* ### CSS modifiers
|
|
37
|
+
* - `opened` — the drawer is open.
|
|
38
|
+
* - `closed` — the drawer is closed.
|
|
39
|
+
*
|
|
40
|
+
* ### CSS elements
|
|
41
|
+
* - `opener`
|
|
42
|
+
* - `closer`
|
|
43
|
+
* - `content`
|
|
44
|
+
*
|
|
45
|
+
* ### CSS custom properties on the root element
|
|
46
|
+
* - `--lm-drawer-content-width` / `--lm-drawer-content-width-raw`
|
|
47
|
+
* - `--lm-drawer-content-height` / `--lm-drawer-content-height-raw`
|
|
48
|
+
* Absent until the first measurement lands.
|
|
49
|
+
*
|
|
50
|
+
* ### Data attributes on the root element
|
|
51
|
+
* - `data-content-width`, `data-content-height` — the measured content size.
|
|
52
|
+
* Absent until the first measurement lands.
|
|
53
|
+
*
|
|
54
|
+
* @param props - Component properties.
|
|
55
|
+
* @see {@link Props}
|
|
56
|
+
* @returns A root `<div>` holding the opener, the closer and the measured content.
|
|
28
57
|
*
|
|
29
58
|
* @remarks
|
|
30
|
-
* - In controlled mode (`isOpened` defined),
|
|
31
|
-
*
|
|
32
|
-
* -
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* --{prefix}-content-height
|
|
36
|
-
* --{prefix}-content-height-px
|
|
37
|
-
* --{prefix}-content-width
|
|
38
|
-
* --{prefix}-content-width-px
|
|
39
|
-
* - As `data-content-width` and `data-content-height` attributes.
|
|
40
|
-
*
|
|
41
|
-
* CSS modifier classes:
|
|
42
|
-
* - `opened` when open
|
|
43
|
-
* - `closed` when closed
|
|
59
|
+
* - In controlled mode (`isOpened` defined), the open state is fully driven by
|
|
60
|
+
* the parent and internal state is never updated.
|
|
61
|
+
* - `onOpenerClicked` and `onCloserClicked` fire in both modes — a controlled
|
|
62
|
+
* parent needs them to know a click happened at all.
|
|
63
|
+
* - `onIsOpenedChanged` fires in both modes too, and never on mount.
|
|
44
64
|
*/
|
|
45
65
|
export declare const Drawer: FunctionComponent<Props>;
|