@inkra/react 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -4
- package/dist/alert-dialog/index.d.ts +1 -1
- package/dist/alert-dialog/index.js +4 -2
- package/dist/command/index.d.ts +24 -2
- package/dist/command/index.js +2 -2
- package/dist/context-menu/index.d.ts +2 -2
- package/dist/context-menu/index.js +3 -2
- package/dist/drawer/index.d.ts +1 -1
- package/dist/drawer/index.js +6 -4
- package/dist/dropdown-menu/index.d.ts +1 -1
- package/dist/dropdown-menu/index.js +3 -2
- package/dist/form/EditablePencilText.js +34 -0
- package/dist/form/Input.js +1 -1
- package/dist/input-number/index.d.ts +6 -0
- package/dist/input-number/index.js +126 -15
- package/dist/input-number/model.d.ts +13 -0
- package/dist/input-number/model.js +50 -0
- package/dist/number-ticker/index.d.ts +11 -9
- package/dist/number-ticker/index.js +14 -11
- package/dist/number-ticker/model.d.ts +38 -5
- package/dist/number-ticker/model.js +139 -10
- package/dist/number-ticker/precision.d.ts +7 -0
- package/dist/number-ticker/precision.js +134 -0
- package/dist/overlay/Overlay.d.ts +1 -1
- package/dist/overlay/Overlay.js +4 -2
- package/dist/overlay/Popover.d.ts +1 -1
- package/dist/overlay/Popover.js +3 -2
- package/dist/overlay/themeBridge.d.ts +12 -1
- package/dist/overlay/themeBridge.js +27 -1
- package/dist/radar/index.d.ts +2 -0
- package/dist/radar/index.js +2 -2
- package/dist/sortable/index.js +9 -4
- package/dist/styles.css +147 -22
- package/dist/tooltip/Tooltip.d.ts +1 -1
- package/dist/tooltip/Tooltip.js +3 -2
- package/dist/virtual-list/index.js +3 -2
- package/package.json +4 -3
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Decimal } from 'decimal.js';
|
|
2
|
+
// Isolated arithmetic context; never change the application's Decimal defaults.
|
|
3
|
+
// Covers the full span of the bounded input exponents and significant digits.
|
|
4
|
+
export const ExactDecimal = Decimal.clone({ precision: 30050, toExpNeg: -7, toExpPos: 21 });
|
|
5
|
+
const decimalPattern = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
6
|
+
const maxDigits = 10000;
|
|
7
|
+
export function tickerDecimal(value) {
|
|
8
|
+
const source = typeof value === 'number' && Object.is(value, -0) ? '-0' : String(value).trim();
|
|
9
|
+
if (typeof value !== 'number') {
|
|
10
|
+
const [coefficient, exponent = '0'] = source.split(/[eE]/);
|
|
11
|
+
if (!decimalPattern.test(source) || coefficient.replace(/\D/g, '').length > maxDigits
|
|
12
|
+
|| exponent.length > 7 || Math.abs(Number(exponent)) > maxDigits) {
|
|
13
|
+
throw new RangeError('NumberTicker requires a decimal value with at most 10000 digits and an exponent between -10000 and 10000');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const decimal = new ExactDecimal(source);
|
|
17
|
+
if (decimal.isFinite() && Math.abs(decimal.e) > maxDigits) {
|
|
18
|
+
throw new RangeError('NumberTicker decimal magnitude exceeds the supported exponent range');
|
|
19
|
+
}
|
|
20
|
+
return decimal;
|
|
21
|
+
}
|
|
22
|
+
export function tickerValueKey(value) {
|
|
23
|
+
return JSON.stringify(value, (_key, item) => typeof item === 'bigint' ? { $bigint: String(item) } : item);
|
|
24
|
+
}
|
|
25
|
+
const roundingModes = {
|
|
26
|
+
ceil: Decimal.ROUND_CEIL, floor: Decimal.ROUND_FLOOR,
|
|
27
|
+
expand: Decimal.ROUND_UP, trunc: Decimal.ROUND_DOWN,
|
|
28
|
+
halfCeil: Decimal.ROUND_HALF_CEIL, halfFloor: Decimal.ROUND_HALF_FLOOR,
|
|
29
|
+
halfExpand: Decimal.ROUND_HALF_UP, halfTrunc: Decimal.ROUND_HALF_DOWN,
|
|
30
|
+
halfEven: Decimal.ROUND_HALF_EVEN,
|
|
31
|
+
};
|
|
32
|
+
function roundedDecimal(value, options) {
|
|
33
|
+
const extra = options;
|
|
34
|
+
const mode = roundingModes[extra.roundingMode ?? 'halfExpand'];
|
|
35
|
+
const maxFraction = options.maximumFractionDigits ?? 0;
|
|
36
|
+
const increment = new ExactDecimal(extra.roundingIncrement ?? 1).times(new ExactDecimal(10).pow(-maxFraction));
|
|
37
|
+
const fraction = value.div(increment).toDecimalPlaces(0, mode).times(increment);
|
|
38
|
+
const significant = options.maximumSignificantDigits === undefined ? null : value.toSignificantDigits(options.maximumSignificantDigits, mode);
|
|
39
|
+
const significantPlace = value.e - (options.maximumSignificantDigits ?? 1) + 1;
|
|
40
|
+
const useSignificant = significant !== null && (extra.roundingPriority === 'morePrecision'
|
|
41
|
+
? significantPlace < -maxFraction : extra.roundingPriority === 'lessPrecision'
|
|
42
|
+
? significantPlace >= -maxFraction : true);
|
|
43
|
+
const rounded = useSignificant ? significant : fraction;
|
|
44
|
+
const decimals = extra.trailingZeroDisplay === 'stripIfInteger' && rounded.isInteger() ? 0
|
|
45
|
+
: useSignificant ? Math.max(0, (options.minimumSignificantDigits ?? 1) - rounded.e - 1)
|
|
46
|
+
: options.minimumFractionDigits ?? 0;
|
|
47
|
+
return { value: rounded, decimals };
|
|
48
|
+
}
|
|
49
|
+
// Intl accepts exact decimal strings in modern engines, but some engines still
|
|
50
|
+
// turn strings beyond Number.MAX_VALUE into Infinity. BigInt bypasses that path.
|
|
51
|
+
export function formatExactParts(formatter, value) {
|
|
52
|
+
if (typeof value === 'number')
|
|
53
|
+
return formatter.formatToParts(value);
|
|
54
|
+
const decimal = Decimal.isDecimal(value) ? value : tickerDecimal(value);
|
|
55
|
+
if (!decimal.isFinite())
|
|
56
|
+
return formatter.formatToParts(decimal.toNumber());
|
|
57
|
+
if (decimal.isZero())
|
|
58
|
+
return formatter.formatToParts(decimal.isNegative() ? -0 : 0);
|
|
59
|
+
if (decimal.isInteger())
|
|
60
|
+
return formatter.formatToParts(BigInt(decimal.toFixed(0)));
|
|
61
|
+
if (decimal.e < 308) {
|
|
62
|
+
const exactFormat = formatter.formatToParts;
|
|
63
|
+
const probe = new Intl.NumberFormat('en-US', { useGrouping: false });
|
|
64
|
+
if (probe.format('9007199254740993') !== '9007199254740993') {
|
|
65
|
+
throw new RangeError('NumberTicker decimal strings require exact Intl.NumberFormat string support');
|
|
66
|
+
}
|
|
67
|
+
return exactFormat.call(formatter, decimal.toString());
|
|
68
|
+
}
|
|
69
|
+
const options = formatter.resolvedOptions();
|
|
70
|
+
// Directed rounding still observes tiny tails at huge magnitudes. Round the
|
|
71
|
+
// mantissa before converting to BigInt, then let Intl supply locale notation.
|
|
72
|
+
if (options.notation === 'scientific' || options.notation === 'engineering') {
|
|
73
|
+
const display = options.style === 'percent' ? decimal.times(100) : decimal;
|
|
74
|
+
const exponent = options.notation === 'engineering' ? Math.floor(display.e / 3) * 3 : display.e;
|
|
75
|
+
const factor = new ExactDecimal(10).pow(exponent);
|
|
76
|
+
const rounded = roundedDecimal(display.div(factor), options).value.times(factor);
|
|
77
|
+
const originalScale = options.style === 'percent' ? rounded.div(100) : rounded;
|
|
78
|
+
return formatter.formatToParts(BigInt(originalScale.toFixed(0)));
|
|
79
|
+
}
|
|
80
|
+
let scaled = options.style === 'percent' ? decimal.times(100) : decimal;
|
|
81
|
+
if (options.notation === 'compact') {
|
|
82
|
+
const probe = new Intl.NumberFormat(options.locale, { ...options, style: 'decimal', useGrouping: false });
|
|
83
|
+
const digits = probe.formatToParts(BigInt(new ExactDecimal(10).pow(scaled.e).toFixed(0)))
|
|
84
|
+
.filter(part => part.type === 'integer').map(part => Array.from(part.value).length).reduce((sum, length) => sum + length, 0);
|
|
85
|
+
scaled = scaled.div(new ExactDecimal(10).pow(scaled.e - digits + 1));
|
|
86
|
+
}
|
|
87
|
+
const rounded = roundedDecimal(scaled, options);
|
|
88
|
+
const [integer, fraction = ''] = rounded.value.abs().toFixed().split('.');
|
|
89
|
+
const fractionalDigits = fraction.padEnd(rounded.decimals, '0');
|
|
90
|
+
const plain = new Intl.NumberFormat(options.locale, {
|
|
91
|
+
numberingSystem: options.numberingSystem, minimumIntegerDigits: options.minimumIntegerDigits,
|
|
92
|
+
useGrouping: options.useGrouping, maximumFractionDigits: 0,
|
|
93
|
+
});
|
|
94
|
+
const numericParts = plain.formatToParts(BigInt(integer));
|
|
95
|
+
if (fractionalDigits) {
|
|
96
|
+
const digits = new Intl.NumberFormat(options.locale, { numberingSystem: options.numberingSystem, useGrouping: false });
|
|
97
|
+
const symbols = Array.from({ length: 10 }, (_, digit) => digits.format(digit));
|
|
98
|
+
numericParts.push({ type: 'decimal', value: digits.formatToParts(1.1).find(part => part.type === 'decimal').value }, { type: 'fraction', value: fractionalDigits.replace(/\d/g, digit => symbols[Number(digit)]) });
|
|
99
|
+
}
|
|
100
|
+
const pattern = formatter.formatToParts(BigInt(decimal.trunc().toFixed(0)));
|
|
101
|
+
// Long unit/currency names depend on the displayed fraction as well as the
|
|
102
|
+
// integer ending. Preserve plural operands without passing an overflowing
|
|
103
|
+
// decimal string to Intl (CLDR cardinal rules inspect at most six end digits).
|
|
104
|
+
const pluralParts = options.style === 'unit' || (options.style === 'currency' && options.currencyDisplay === 'name')
|
|
105
|
+
? formatExactParts(new Intl.NumberFormat(options.locale, {
|
|
106
|
+
numberingSystem: options.numberingSystem, style: options.style,
|
|
107
|
+
unit: options.unit, unitDisplay: options.unitDisplay,
|
|
108
|
+
currency: options.currency, currencyDisplay: options.currencyDisplay,
|
|
109
|
+
minimumFractionDigits: fractionalDigits.length, maximumFractionDigits: fractionalDigits.length,
|
|
110
|
+
}), `${BigInt(integer) > 1000000n ? 1000000n + BigInt(integer) % 1000000n : BigInt(integer)}${fractionalDigits ? `.${fractionalDigits}` : ''}`)
|
|
111
|
+
: undefined;
|
|
112
|
+
let inserted = false;
|
|
113
|
+
return pattern.flatMap(part => {
|
|
114
|
+
if (part.type === 'unit' || part.type === 'currency') {
|
|
115
|
+
return [pluralParts?.find(candidate => candidate.type === part.type) ?? part];
|
|
116
|
+
}
|
|
117
|
+
if (!['integer', 'group', 'decimal', 'fraction'].includes(part.type))
|
|
118
|
+
return [part];
|
|
119
|
+
if (inserted)
|
|
120
|
+
return [];
|
|
121
|
+
inserted = true;
|
|
122
|
+
return numericParts;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
export function subtractTickerValues(next, previous) {
|
|
126
|
+
const to = tickerDecimal(next);
|
|
127
|
+
const from = tickerDecimal(previous);
|
|
128
|
+
if (!to.isFinite() || !from.isFinite())
|
|
129
|
+
return null;
|
|
130
|
+
if (typeof next === 'number' && typeof previous === 'number')
|
|
131
|
+
return next - previous;
|
|
132
|
+
const difference = to.minus(from);
|
|
133
|
+
return typeof next === 'bigint' && typeof previous === 'bigint' ? BigInt(difference.toFixed(0)) : difference.toString();
|
|
134
|
+
}
|
|
@@ -7,7 +7,7 @@ export declare function OverlayRoot(props: OverlayRootProps): import("react").JS
|
|
|
7
7
|
export type OverlayTriggerProps = DialogPrimitive.DialogTriggerProps;
|
|
8
8
|
export declare const OverlayTrigger: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
9
9
|
export type OverlayPortalProps = DialogPrimitive.DialogPortalProps;
|
|
10
|
-
export declare function OverlayPortal({ children, ...props }: OverlayPortalProps):
|
|
10
|
+
export declare function OverlayPortal({ children, ...props }: OverlayPortalProps): ReactNode;
|
|
11
11
|
export type OverlayBackdropProps = DialogPrimitive.DialogOverlayProps;
|
|
12
12
|
export declare const OverlayBackdrop: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogOverlayProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
13
13
|
export interface OverlayContentProps extends DialogPrimitive.DialogContentProps {
|
package/dist/overlay/Overlay.js
CHANGED
|
@@ -8,7 +8,7 @@ import { PencilLine } from '../PencilLine.js';
|
|
|
8
8
|
import { PencilSurface } from '../PencilSurface.js';
|
|
9
9
|
import { PencilText } from '../PencilText.js';
|
|
10
10
|
import { Tooltip } from '../tooltip/Tooltip.js';
|
|
11
|
-
import {
|
|
11
|
+
import { mapPortalChildren, PortalThemeProvider, usePortalThemeProps, usePortalTriggerRef, } from './themeBridge.js';
|
|
12
12
|
function classes(...values) {
|
|
13
13
|
return values.filter(Boolean).join(' ');
|
|
14
14
|
}
|
|
@@ -20,13 +20,15 @@ export const OverlayTrigger = forwardRef(function OverlayTrigger(props, forwarde
|
|
|
20
20
|
return _jsx(DialogPrimitive.Trigger, { ...props, ref: ref });
|
|
21
21
|
});
|
|
22
22
|
export function OverlayPortal({ children, ...props }) {
|
|
23
|
-
return (_jsx(DialogPrimitive.Portal, { ...props, children:
|
|
23
|
+
return mapPortalChildren(children, child => _jsx(DialogPrimitive.Portal, { ...props, children: child }));
|
|
24
24
|
}
|
|
25
25
|
export const OverlayBackdrop = forwardRef(function OverlayBackdrop({ className, ...props }, ref) {
|
|
26
|
+
props = usePortalThemeProps(props);
|
|
26
27
|
return (_jsx(DialogPrimitive.Overlay, { ...props, className: classes('inkra-overlay__backdrop', className), ref: ref }));
|
|
27
28
|
});
|
|
28
29
|
export const OverlayContent = forwardRef(function OverlayContent({ children, className, layout = 'plain', seed, surfaceClassName, surfaceRadius = 8, surfaceVariant = 'paper', ...props }, ref) {
|
|
29
30
|
const id = useId();
|
|
31
|
+
props = usePortalThemeProps(props);
|
|
30
32
|
return (_jsx(DialogPrimitive.Content, { ...props, className: classes('inkra-overlay__content', className), "data-layout": layout, ref: ref, children: _jsx(PencilSurface, { className: classes('inkra-overlay__surface', surfaceClassName), radius: surfaceRadius, seed: seed ?? `inkra-overlay-${id}`, variant: surfaceVariant, children: _jsx("div", { className: "inkra-overlay__content-body", children: children }) }) }));
|
|
31
33
|
});
|
|
32
34
|
export const OverlayTitle = forwardRef(function OverlayTitle({ children, className, seed, ...props }, ref) {
|
|
@@ -8,7 +8,7 @@ export declare const PopoverAnchor: import("react").ForwardRefExoticComponent<Po
|
|
|
8
8
|
export type PopoverTriggerProps = PopoverPrimitive.PopoverTriggerProps;
|
|
9
9
|
export declare const PopoverTrigger: import("react").ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
10
10
|
export type PopoverPortalProps = PopoverPrimitive.PopoverPortalProps;
|
|
11
|
-
export declare function PopoverPortal({ children, ...props }: PopoverPortalProps): import("react").
|
|
11
|
+
export declare function PopoverPortal({ children, ...props }: PopoverPortalProps): import("react").ReactNode;
|
|
12
12
|
export interface PopoverContentProps extends PopoverPrimitive.PopoverContentProps {
|
|
13
13
|
arrowProps?: PopoverArrowProps;
|
|
14
14
|
seed?: string | number;
|
package/dist/overlay/Popover.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
|
3
3
|
import { forwardRef, useId } from 'react';
|
|
4
4
|
import { PencilSurface } from '../PencilSurface.js';
|
|
5
5
|
import { PencilText } from '../PencilText.js';
|
|
6
|
-
import {
|
|
6
|
+
import { mapPortalChildren, PortalThemeProvider, usePortalThemeProps, usePortalTriggerRef, } from './themeBridge.js';
|
|
7
7
|
function classes(...values) {
|
|
8
8
|
return values.filter(Boolean).join(' ');
|
|
9
9
|
}
|
|
@@ -16,10 +16,11 @@ export const PopoverTrigger = forwardRef(function PopoverTrigger(props, forwarde
|
|
|
16
16
|
return _jsx(PopoverPrimitive.Trigger, { ...props, ref: ref });
|
|
17
17
|
});
|
|
18
18
|
export function PopoverPortal({ children, ...props }) {
|
|
19
|
-
return (_jsx(PopoverPrimitive.Portal, { ...props, children:
|
|
19
|
+
return mapPortalChildren(children, child => _jsx(PopoverPrimitive.Portal, { ...props, children: child }));
|
|
20
20
|
}
|
|
21
21
|
export const PopoverContent = forwardRef(function PopoverContent({ arrowProps, children, className, seed, showArrow = false, surfaceClassName, surfaceRadius = 8, surfaceVariant = 'paper', ...props }, ref) {
|
|
22
22
|
const id = useId();
|
|
23
|
+
props = usePortalThemeProps(props);
|
|
23
24
|
return (_jsxs(PopoverPrimitive.Content, { ...props, className: classes('inkra-popover__content', className), ref: ref, children: [_jsx(PencilSurface, { className: classes('inkra-popover__surface', surfaceClassName), radius: surfaceRadius, seed: seed ?? `inkra-popover-${id}`, variant: surfaceVariant, children: _jsx("div", { className: "inkra-popover__content-body", children: children }) }), showArrow ? (_jsx(PopoverPrimitive.Arrow, { ...arrowProps, className: classes('inkra-popover__arrow', arrowProps?.className) })) : null] }));
|
|
24
25
|
});
|
|
25
26
|
export const PopoverTitle = forwardRef(function PopoverTitle({ children, className, seed, ...props }, ref) {
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
import type { ForwardedRef, ReactNode } from 'react';
|
|
1
|
+
import type { CSSProperties, ForwardedRef, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
type InkraStyle = CSSProperties & Record<`--inkra-${string}`, string>;
|
|
2
3
|
export declare function PortalThemeProvider({ children }: {
|
|
3
4
|
children: ReactNode;
|
|
4
5
|
}): import("react").JSX.Element;
|
|
5
6
|
export declare function usePortalTriggerRef<Element extends HTMLElement>(forwardedRef: ForwardedRef<Element>): (node: Element | null) => void;
|
|
7
|
+
export declare function mapPortalChildren(children: ReactNode, render: (child: ReactNode) => ReactNode): ReactNode;
|
|
8
|
+
export declare function usePortalThemeProps<Props extends HTMLAttributes<HTMLElement>>(props: Props): {
|
|
9
|
+
'data-inkra-theme': string | undefined;
|
|
10
|
+
'data-theme': string | undefined;
|
|
11
|
+
dir: "ltr" | "rtl";
|
|
12
|
+
lang: string | undefined;
|
|
13
|
+
} & Props & {
|
|
14
|
+
style: InkraStyle;
|
|
15
|
+
};
|
|
6
16
|
export declare const PortalThemeBridge: import("react").ForwardRefExoticComponent<{
|
|
7
17
|
children: ReactNode;
|
|
8
18
|
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
19
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, forwardRef, useCallback, useContext, useEffect, useMemo, useState, } from 'react';
|
|
2
|
+
import { Children, Fragment, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useMemo, useState, } from 'react';
|
|
3
3
|
const emptySnapshot = {
|
|
4
4
|
direction: 'ltr',
|
|
5
5
|
style: {},
|
|
@@ -86,6 +86,32 @@ export function usePortalTriggerRef(forwardedRef) {
|
|
|
86
86
|
captureTrigger?.(node);
|
|
87
87
|
}, [captureTrigger, forwardedRef]);
|
|
88
88
|
}
|
|
89
|
+
// Presence must receive each animated DOM node, not a display:contents wrapper.
|
|
90
|
+
export function mapPortalChildren(children, render) {
|
|
91
|
+
return Children.map(children, child => {
|
|
92
|
+
if (isValidElement(child) && child.type === Fragment) {
|
|
93
|
+
return mapPortalChildren(child.props.children, render);
|
|
94
|
+
}
|
|
95
|
+
return child == null ? null : render(child);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
export function usePortalThemeProps(props) {
|
|
99
|
+
const context = useContext(PortalThemeContext);
|
|
100
|
+
const depth = context?.depth ?? 0;
|
|
101
|
+
const snapshot = context?.snapshot ?? emptySnapshot;
|
|
102
|
+
return {
|
|
103
|
+
'data-inkra-theme': snapshot.inkraTheme,
|
|
104
|
+
'data-theme': snapshot.theme,
|
|
105
|
+
dir: snapshot.direction,
|
|
106
|
+
lang: snapshot.language,
|
|
107
|
+
...props,
|
|
108
|
+
style: {
|
|
109
|
+
...snapshot.style,
|
|
110
|
+
'--inkra-floating-layer-offset': `${depth * 20}`,
|
|
111
|
+
...props.style,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
89
115
|
export const PortalThemeBridge = forwardRef(function PortalThemeBridge({ children }, ref) {
|
|
90
116
|
const context = useContext(PortalThemeContext);
|
|
91
117
|
const depth = context?.depth ?? 0;
|
package/dist/radar/index.d.ts
CHANGED
|
@@ -42,6 +42,8 @@ export interface RadarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'childr
|
|
|
42
42
|
showValues?: boolean;
|
|
43
43
|
showTable?: boolean;
|
|
44
44
|
legendLabel?: ReactNode;
|
|
45
|
+
tableCaption?: ReactNode;
|
|
46
|
+
seriesLabel?: ReactNode;
|
|
45
47
|
missingLabel?: string;
|
|
46
48
|
emptyMessage?: ReactNode;
|
|
47
49
|
selectedSeries?: RadarKey | null;
|
package/dist/radar/index.js
CHANGED
|
@@ -169,7 +169,7 @@ function domainForAxis(axis, values) {
|
|
|
169
169
|
function paintStyle(color) {
|
|
170
170
|
return { '--inkra-accent': color, '--inkra-accent-soft': color, '--inkra-accent-strong': color };
|
|
171
171
|
}
|
|
172
|
-
export const Radar = forwardRef(function Radar({ axes, series, label, description, size = 'min(100%, 34rem)', maxRadius, levels = 4, showAxes = true, showLabels = true, showLegend = true, showValues = true, showTable = true, legendLabel = 'Series', missingLabel = 'Missing', emptyMessage = 'No radar data', selectedSeries, defaultSelectedSeries = null, onSelectedSeriesChange, renderAxisLabel, renderValueLabel, getValueLabel, className, style, ...props }, forwardedRef) {
|
|
172
|
+
export const Radar = forwardRef(function Radar({ axes, series, label, description, size = 'min(100%, 34rem)', maxRadius, levels = 4, showAxes = true, showLabels = true, showLegend = true, showValues = true, showTable = true, legendLabel = 'Series', tableCaption = 'Radar data', seriesLabel = 'Series', missingLabel = 'Missing', emptyMessage = 'No radar data', selectedSeries, defaultSelectedSeries = null, onSelectedSeriesChange, renderAxisLabel, renderValueLabel, getValueLabel, className, style, ...props }, forwardedRef) {
|
|
173
173
|
const id = useId();
|
|
174
174
|
const labelId = `inkra-radar-${id}-label`;
|
|
175
175
|
const descriptionId = description == null ? undefined : `inkra-radar-${id}-description`;
|
|
@@ -216,5 +216,5 @@ export const Radar = forwardRef(function Radar({ axes, series, label, descriptio
|
|
|
216
216
|
const context = { axis: point.axis, series: item, point: point.point, value: point.value, missing: point.value == null };
|
|
217
217
|
return _jsxs("span", { className: "inkra-radar__value", "data-missing": context.missing || undefined, children: [_jsx("strong", { children: textNode(point.axis.label, `${id}-value-axis-${String(point.axis.id)}`) }), " ", textNode(renderValue(context), `${id}-value-${String(item.id)}-${String(point.axis.id)}`)] }, pointIndex);
|
|
218
218
|
}) })] }, keyPart(item.id));
|
|
219
|
-
}) }), showLegend ? _jsxs("div", { "aria-label": typeof legendLabel === 'string' ? legendLabel : undefined, className: "inkra-radar__legend", role: "group", children: [_jsx("span", { className: "inkra-radar__legend-title", children: textNode(legendLabel, `${id}-legend-title`) }), visibleSeries.map((item, index) => _jsxs(Button, { "aria-pressed": sameKey(selected, item.id), className: "inkra-radar__legend-button", onClick: () => selectSeries(item), size: "sm", variant: "ghost", children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-radar__legend-mark", radius: 4, seed: `radar-legend-${keyPart(item.id)}`, style: paintStyle(item.color ?? palette[index % palette.length]), variant: sameKey(selected, item.id) ? 'selection' : 'quiet' }), textNode(item.label, `${id}-legend-${String(item.id)}`)] }, keyPart(item.id)))] }) : null, showTable ? _jsx(Table.Container, { "aria-label": typeof label === 'string' ? label : undefined, "aria-describedby": descriptionId, children: _jsxs(Table.Root, { className: "inkra-radar__table", children: [_jsx(Table.Caption, { children: textNode(
|
|
219
|
+
}) }), showLegend ? _jsxs("div", { "aria-label": typeof legendLabel === 'string' ? legendLabel : undefined, className: "inkra-radar__legend", role: "group", children: [_jsx("span", { className: "inkra-radar__legend-title", children: textNode(legendLabel, `${id}-legend-title`) }), visibleSeries.map((item, index) => _jsxs(Button, { "aria-pressed": sameKey(selected, item.id), className: "inkra-radar__legend-button", onClick: () => selectSeries(item), size: "sm", variant: "ghost", children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-radar__legend-mark", radius: 4, seed: `radar-legend-${keyPart(item.id)}`, style: paintStyle(item.color ?? palette[index % palette.length]), variant: sameKey(selected, item.id) ? 'selection' : 'quiet' }), textNode(item.label, `${id}-legend-${String(item.id)}`)] }, keyPart(item.id)))] }) : null, showTable ? _jsx(Table.Container, { "aria-label": typeof label === 'string' ? label : undefined, "aria-describedby": descriptionId, children: _jsxs(Table.Root, { className: "inkra-radar__table", children: [_jsx(Table.Caption, { children: textNode(tableCaption, `${id}-table-caption`) }), _jsx(Table.Header, { children: _jsxs(Table.Row, { children: [_jsx(Table.Head, { children: textNode(seriesLabel, `${id}-table-series`) }), axes.map(axis => _jsx(Table.Head, { children: textNode(axis.label, `${id}-table-axis-${String(axis.id)}`) }, keyPart(axis.id)))] }) }), _jsx(Table.Body, { children: visibleSeries.map(item => _jsxs(Table.Row, { children: [_jsx(Table.Head, { scope: "row", children: textNode(item.label, `${id}-table-series-${String(item.id)}`) }), axes.map(axis => { const point = item.data.find(candidate => candidate.axisId === axis.id); const missing = !finite(point?.value); return _jsx(Table.Cell, { "data-missing": missing || undefined, children: textNode(missing ? missingLabel : formatNumber(point?.value, axis, getValueLabel), `${id}-table-value-${String(item.id)}-${String(axis.id)}`) }, keyPart(axis.id)); })] }, keyPart(item.id))) })] }) }) : null] })] });
|
|
220
220
|
});
|
package/dist/sortable/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { __iconData as gripIconData } from 'lucide-react/dist/esm/icons/grip-vertical.mjs';
|
|
2
3
|
import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, closestCenter, pointerWithin, rectIntersection, useDroppable, useSensor, useSensors, } from '@dnd-kit/core';
|
|
3
4
|
import { SortableContext, rectSortingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
4
5
|
import { CSS } from '@dnd-kit/utilities';
|
|
@@ -8,9 +9,13 @@ import { PencilLine } from '../PencilLine.js';
|
|
|
8
9
|
import { PencilSurface } from '../PencilSurface.js';
|
|
9
10
|
import { PencilText } from '../PencilText.js';
|
|
10
11
|
import { cloneSortableContainers, findSortableLocation, projectSortableMove, sortableContainersEqual, } from './model.js';
|
|
11
|
-
const gripIcon = [
|
|
12
|
-
{
|
|
13
|
-
|
|
12
|
+
const gripIcon = gripIconData.node.map(([, attributes]) => {
|
|
13
|
+
const { cx, cy, r } = attributes;
|
|
14
|
+
const x = Number(cx);
|
|
15
|
+
const y = Number(cy);
|
|
16
|
+
const radius = Number(r);
|
|
17
|
+
return { d: `M ${x - radius} ${y} A ${radius} ${radius} 0 1 0 ${x + radius} ${y} A ${radius} ${radius} 0 1 0 ${x - radius} ${y}` };
|
|
18
|
+
});
|
|
14
19
|
function engineItemId(id) {
|
|
15
20
|
return `inkra-sortable-item:${typeof id}:${String(id)}`;
|
|
16
21
|
}
|
|
@@ -128,7 +133,7 @@ function SortableItem({ activeId, container, disabled, handle, handleLabel, id,
|
|
|
128
133
|
if (!hasHandle)
|
|
129
134
|
setActivatorNodeRef(element);
|
|
130
135
|
};
|
|
131
|
-
return _jsxs("div", { ...(!hasHandle ? itemActivatorProps : {}), "aria-disabled": disabled || undefined, className: ['inkra-sortable__item', itemClassName].filter(Boolean).join(' '), "data-disabled": disabled || undefined, "data-dragging": isDragging || undefined, "data-sortable-id": String(id), ref: setItemRef, style: { transform: CSS.Transform.toString(transform), transition }, children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-sortable__item-surface", seed: `sortable-item-${String(id)}`, variant: "paper" }), _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-sortable__focus", seed: `sortable-focus-${String(id)}`, variant: "outline" }), activeId === id && _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-sortable__placeholder", seed: `sortable-placeholder-${String(id)}`, variant: "selection" }), _jsx("div", { className: "inkra-sortable__item-content", children: renderItem(state) }), hasHandle && _jsx("div", { className: "inkra-sortable__handle-slot", children: typeof handle === 'function'
|
|
136
|
+
return _jsxs("div", { ...(!hasHandle ? itemActivatorProps : {}), "aria-disabled": disabled || undefined, "aria-label": !hasHandle ? handleLabel : undefined, className: ['inkra-sortable__item', itemClassName].filter(Boolean).join(' '), "data-disabled": disabled || undefined, "data-dragging": isDragging || undefined, "data-handle": hasHandle || undefined, "data-sortable-id": String(id), ref: setItemRef, style: { transform: CSS.Transform.toString(transform), transition }, children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-sortable__item-surface", seed: `sortable-item-${String(id)}`, variant: "paper" }), _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-sortable__focus", seed: `sortable-focus-${String(id)}`, variant: "outline" }), activeId === id && _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-sortable__placeholder", seed: `sortable-placeholder-${String(id)}`, variant: "selection" }), _jsx("div", { className: "inkra-sortable__item-content", children: renderItem(state) }), hasHandle && _jsx("div", { className: "inkra-sortable__handle-slot", children: typeof handle === 'function'
|
|
132
137
|
? handle({ ...state, props: { ...activatorProps, 'aria-label': handleLabel, disabled, ref: setActivatorNodeRef } })
|
|
133
138
|
: _jsx("button", { ...activatorProps, "aria-label": handleLabel, className: "inkra-sortable__handle", "data-sortable-handle": "", disabled: disabled, ref: setActivatorNodeRef, type: "button", children: _jsx(PencilIcon, { "aria-hidden": "true", paths: gripIcon, size: 24, sourceSize: 24 }) }) })] });
|
|
134
139
|
}
|