@inkra/react 0.4.3 → 0.5.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 +98 -0
- package/dist/audio-player/index.js +6 -4
- package/dist/breadcrumb/index.js +4 -1
- package/dist/calendar/index.js +10 -4
- package/dist/calendar/locales.d.ts +7 -0
- package/dist/calendar/locales.js +2 -0
- package/dist/carousel/index.js +8 -5
- package/dist/choice-grid/index.js +3 -1
- package/dist/color-picker/GradientEditor.d.ts +2 -1
- package/dist/color-picker/GradientEditor.js +10 -9
- package/dist/color-picker/index.js +12 -10
- package/dist/content/index.js +4 -1
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +4 -1
- package/dist/date-picker/index.js +11 -13
- package/dist/day-agenda/index.d.ts +1 -1
- package/dist/day-agenda/index.js +4 -1
- package/dist/dockable-panel/index.js +10 -8
- package/dist/drawer/index.js +7 -2
- package/dist/editable/index.js +8 -5
- package/dist/form/Input.js +4 -1
- package/dist/form/Textarea.js +4 -2
- package/dist/heatmap/index.js +4 -1
- package/dist/hotkey/index.js +4 -1
- package/dist/i18n/catalog.d.ts +5 -0
- package/dist/i18n/catalog.js +289 -0
- package/dist/i18n/index.d.ts +23 -0
- package/dist/i18n/index.js +50 -0
- package/dist/image-cropper/index.js +17 -15
- package/dist/image-viewer/VideoResource.js +14 -12
- package/dist/image-viewer/index.js +23 -21
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/input-number/index.js +4 -1
- package/dist/internal/textRenderer.d.ts +1 -0
- package/dist/internal/textRenderer.js +10 -2
- package/dist/journey-map/index.d.ts +1 -1
- package/dist/journey-map/index.js +6 -3
- package/dist/keypad/index.js +4 -1
- package/dist/log/index.js +13 -11
- package/dist/markdown/index.js +11 -9
- package/dist/node-graph/index.d.ts +1 -1
- package/dist/node-graph/index.js +14 -3
- package/dist/number-ticker/index.js +4 -1
- package/dist/overflow-list/index.js +4 -4
- package/dist/overlay/Overlay.js +7 -2
- package/dist/pagination/index.js +7 -5
- package/dist/pan-zoom/index.js +6 -3
- package/dist/radar/index.js +4 -1
- package/dist/range-slider/index.js +4 -3
- package/dist/rating/index.js +5 -2
- package/dist/resizable/index.d.ts +1 -1
- package/dist/resizable/index.js +4 -1
- package/dist/select/SearchableSelect.js +3 -1
- package/dist/select/Select.js +3 -1
- package/dist/select/StepperSelect.js +4 -1
- package/dist/sortable/index.js +11 -9
- package/dist/sparkline/index.js +7 -7
- package/dist/steps/index.js +4 -1
- package/dist/styles/select.css +1 -4
- package/dist/styles.css +1 -4
- package/dist/tabs/index.js +4 -1
- package/dist/tag-input/index.js +12 -17
- package/dist/theme/index.d.ts +11 -0
- package/dist/theme/index.js +23 -0
- package/dist/time-picker/index.js +7 -7
- package/dist/timeline/index.js +4 -1
- package/dist/toast/index.d.ts +1 -1
- package/dist/toast/index.js +4 -1
- package/dist/transfer/index.js +30 -27
- package/dist/tree/index.js +7 -2
- package/dist/tree-select/index.js +3 -1
- package/dist/upload/index.js +21 -18
- package/dist/virtual-list/index.js +4 -1
- package/package.json +11 -1
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 { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { __iconData as gripIconData } from 'lucide-react/dist/esm/icons/grip-vertical.mjs';
|
|
3
4
|
import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, closestCenter, pointerWithin, rectIntersection, useDroppable, useSensor, useSensors, } from '@dnd-kit/core';
|
|
4
5
|
import { SortableContext, rectSortingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
@@ -42,14 +43,14 @@ function filterItemActivatorProps(props) {
|
|
|
42
43
|
},
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
|
-
const defaultLabels = {
|
|
46
|
-
handle: '
|
|
47
|
-
screenReaderInstructions: '
|
|
48
|
-
pickedUp: (item, container, position, count) =>
|
|
49
|
-
movedOver: (item, container, position, count) =>
|
|
50
|
-
dropped: (item, container, position, count) =>
|
|
51
|
-
cancelled:
|
|
52
|
-
};
|
|
46
|
+
const defaultLabels = (t) => ({
|
|
47
|
+
handle: t('sortable.handle'),
|
|
48
|
+
screenReaderInstructions: t('sortable.instructions'),
|
|
49
|
+
pickedUp: (item, container, position, count) => t('sortable.pickedUp', { item, container, position, count }),
|
|
50
|
+
movedOver: (item, container, position, count) => t('sortable.movedOver', { item, container, position, count }),
|
|
51
|
+
dropped: (item, container, position, count) => t('sortable.dropped', { item, container, position, count }),
|
|
52
|
+
cancelled: item => t('sortable.cancelled', { item }),
|
|
53
|
+
});
|
|
53
54
|
function getEngineData(value) {
|
|
54
55
|
const data = value?.data.current;
|
|
55
56
|
return data?.type === 'inkra-sortable-item' || data?.type === 'inkra-sortable-container' ? data : null;
|
|
@@ -138,7 +139,8 @@ function SortableItem({ activeId, container, disabled, handle, handleLabel, id,
|
|
|
138
139
|
: _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 }) }) })] });
|
|
139
140
|
}
|
|
140
141
|
export function Sortable({ autoScroll = true, className, containerClassName, containers, getContainerLabel = (container) => container.label ?? String(container.id), getItemId, getItemLabel = (item) => String(getItemId(item)), handle = false, isItemDisabled, itemClassName, labels: labelsProp, onChange, onMove, onReorder, renderContainerHeader, renderItem, renderOverlay, }) {
|
|
141
|
-
const
|
|
142
|
+
const { t } = useInkraLocale();
|
|
143
|
+
const labels = useMemo(() => ({ ...defaultLabels(t), ...labelsProp }), [t, labelsProp]);
|
|
142
144
|
const [activeId, setActiveId] = useState(null);
|
|
143
145
|
const [activeWidth, setActiveWidth] = useState(null);
|
|
144
146
|
const [projected, setProjected] = useState(null);
|
package/dist/sparkline/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { forwardRef, useMemo, useRef, useState } from 'react';
|
|
3
4
|
import { PencilText } from '../PencilText.js';
|
|
4
5
|
import { useBrowserLayoutEffect } from '../internal/useBrowserLayoutEffect.js';
|
|
@@ -9,9 +10,6 @@ import { pencilStroke } from '../internal/stroke.js';
|
|
|
9
10
|
import { drawPencilWash } from '../internal/wash.js';
|
|
10
11
|
import { pencilRenderDefaults, readRenderToken } from '../internal/renderTokens.js';
|
|
11
12
|
import { createSparklineGeometry, normalizeSparklineData, sparklineDomain } from './model.js';
|
|
12
|
-
function defaultLabel(value, index) {
|
|
13
|
-
return value === null ? `Point ${index + 1}: missing` : `Point ${index + 1}: ${value}`;
|
|
14
|
-
}
|
|
15
13
|
function resolveCssColor(host, style, token, fallback) {
|
|
16
14
|
const value = style.getPropertyValue(token).trim();
|
|
17
15
|
if (!value || !value.includes('var('))
|
|
@@ -23,7 +21,9 @@ function resolveCssColor(host, style, token, fallback) {
|
|
|
23
21
|
probe.remove();
|
|
24
22
|
return resolved || fallback;
|
|
25
23
|
}
|
|
26
|
-
export const Sparkline = forwardRef(function Sparkline(
|
|
24
|
+
export const Sparkline = forwardRef(function Sparkline(inkraProps, ref) {
|
|
25
|
+
const { t } = useInkraLocale();
|
|
26
|
+
const { data, type = 'line', width = 180, height = 56, min, max, label = t('sparkline.label'), showPoints = true, showArea = true, showSummary = true, getLabel = (value, index) => t(value === null ? 'sparkline.missing' : 'sparkline.point', { index: index + 1, value: value ?? '' }), className, ...props } = inkraProps;
|
|
27
27
|
const canvasRef = useRef(null);
|
|
28
28
|
const interactionCanvasRef = useRef(null);
|
|
29
29
|
const [pencilReady, setPencilReady] = useState(false);
|
|
@@ -46,15 +46,15 @@ export const Sparkline = forwardRef(function Sparkline({ data, type = 'line', wi
|
|
|
46
46
|
const effectiveShowPoints = showPoints || values.length === 1;
|
|
47
47
|
const summary = useMemo(() => {
|
|
48
48
|
if (!values.length)
|
|
49
|
-
return '
|
|
49
|
+
return t('sparkline.empty');
|
|
50
50
|
let minimum = values[0];
|
|
51
51
|
let maximum = values[0];
|
|
52
52
|
for (let index = 1; index < values.length; index++) {
|
|
53
53
|
minimum = Math.min(minimum, values[index]);
|
|
54
54
|
maximum = Math.max(maximum, values[index]);
|
|
55
55
|
}
|
|
56
|
-
return
|
|
57
|
-
}, [values]);
|
|
56
|
+
return t('sparkline.summary', { current: values[values.length - 1], minimum, maximum });
|
|
57
|
+
}, [t, values]);
|
|
58
58
|
const onKeyDown = (event) => {
|
|
59
59
|
if (!points.length || !['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key))
|
|
60
60
|
return;
|
package/dist/steps/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { forwardRef } from 'react';
|
|
3
4
|
import { PencilIcon } from '../PencilIcon.js';
|
|
4
5
|
import { PencilLine } from '../PencilLine.js';
|
|
@@ -20,7 +21,9 @@ function resolvedStatus(item, index, current) {
|
|
|
20
21
|
return 'current';
|
|
21
22
|
return 'upcoming';
|
|
22
23
|
}
|
|
23
|
-
export const Steps = forwardRef(function Steps(
|
|
24
|
+
export const Steps = forwardRef(function Steps(inkraProps, ref) {
|
|
25
|
+
const { t } = useInkraLocale();
|
|
26
|
+
const { 'aria-label': ariaLabel = t('steps.label'), className, current = 0, items, onStepChange, orientation = 'horizontal', ...props } = inkraProps;
|
|
24
27
|
return _jsx("ol", { ...props, ref: ref, "aria-label": ariaLabel, className: ['inkra-steps', className].filter(Boolean).join(' '), "data-orientation": orientation, children: items.map((item, index) => {
|
|
25
28
|
const status = resolvedStatus(item, index, current);
|
|
26
29
|
const interactive = onStepChange !== undefined;
|
package/dist/styles/select.css
CHANGED
|
@@ -23,11 +23,8 @@
|
|
|
23
23
|
.inkra-search-select__input .inkra-search-select__input-control > .inkra-pencil-surface__border { display: none; }
|
|
24
24
|
.inkra-search-select__anchor > .inkra-input__end-action { flex: 0 0 auto; }
|
|
25
25
|
.inkra-search-select__anchor > .inkra-input__end-action:has(.inkra-search-select__clear:not([data-visible])) {
|
|
26
|
-
|
|
26
|
+
display: none;
|
|
27
27
|
}
|
|
28
|
-
.inkra-search-select__anchor > .inkra-input__end-action:has(.inkra-search-select__clear:not([data-visible]))
|
|
29
|
-
> :is(.inkra-input__action-divider, .inkra-input__action-wash) { display: none; }
|
|
30
|
-
.inkra-search-select__clear:not([data-visible]) { visibility: hidden; }
|
|
31
28
|
.inkra-search-select__trigger .inkra-button__content,
|
|
32
29
|
.inkra-search-select__trigger .inkra-button__label,
|
|
33
30
|
.inkra-search-select__trigger .inkra-button__label > span { min-width: 0; width: 100%; }
|
package/dist/styles.css
CHANGED
|
@@ -2015,11 +2015,8 @@
|
|
|
2015
2015
|
.inkra-search-select__input .inkra-search-select__input-control > .inkra-pencil-surface__border { display: none; }
|
|
2016
2016
|
.inkra-search-select__anchor > .inkra-input__end-action { flex: 0 0 auto; }
|
|
2017
2017
|
.inkra-search-select__anchor > .inkra-input__end-action:has(.inkra-search-select__clear:not([data-visible])) {
|
|
2018
|
-
|
|
2018
|
+
display: none;
|
|
2019
2019
|
}
|
|
2020
|
-
.inkra-search-select__anchor > .inkra-input__end-action:has(.inkra-search-select__clear:not([data-visible]))
|
|
2021
|
-
> :is(.inkra-input__action-divider, .inkra-input__action-wash) { display: none; }
|
|
2022
|
-
.inkra-search-select__clear:not([data-visible]) { visibility: hidden; }
|
|
2023
2020
|
.inkra-search-select__trigger .inkra-button__content,
|
|
2024
2021
|
.inkra-search-select__trigger .inkra-button__label,
|
|
2025
2022
|
.inkra-search-select__trigger .inkra-button__label > span { min-width: 0; width: 100%; }
|
package/dist/tabs/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import * as Primitive from '@radix-ui/react-tabs';
|
|
3
4
|
import { createContext, forwardRef, useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
4
5
|
import { __iconData as chevronLeft } from 'lucide-react/dist/esm/icons/chevron-left.mjs';
|
|
@@ -43,7 +44,9 @@ const Root = forwardRef(function TabsRoot({ value, defaultValue, onValueChange,
|
|
|
43
44
|
};
|
|
44
45
|
return _jsx(ValueContext.Provider, { value: current, children: _jsx(ChangeContext.Provider, { value: change, children: _jsx(AnimatedContext.Provider, { value: animated, children: _jsx(OrientationContext.Provider, { value: orientation, children: _jsx(Primitive.Root, { ...props, orientation: orientation, ref: ref, "data-size": size, className: ['inkra-tabs', className].filter(Boolean).join(' '), value: current ?? '', onValueChange: change }) }) }) }) });
|
|
45
46
|
});
|
|
46
|
-
const List = forwardRef(function TabsList(
|
|
47
|
+
const List = forwardRef(function TabsList(inkraProps, ref) {
|
|
48
|
+
const { t } = useInkraLocale();
|
|
49
|
+
const { className, align = 'start', fullWidth = false, divided = false, overflow = 'scroll', moreLabel = t('tabs.more'), scrollPreviousLabel = t('tabs.previous'), scrollNextLabel = t('tabs.next'), onFocusCapture, ...props } = inkraProps;
|
|
47
50
|
const current = useContext(ValueContext);
|
|
48
51
|
const change = useContext(ChangeContext);
|
|
49
52
|
const mode = useContext(OrientationContext) === 'horizontal' ? overflow : 'scroll';
|
package/dist/tag-input/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { forwardRef, memo, useCallback, useEffect, useId, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
3
4
|
import { PencilIcon } from '../PencilIcon.js';
|
|
4
5
|
import { Button } from '../Button.js';
|
|
@@ -10,26 +11,18 @@ import { createDefaultTag, defaultTagInputDelimiters, defaultTagValueKey, normal
|
|
|
10
11
|
const removePaths = [{ d: 'M18 6 6 18' }, { d: 'm6 6 12 12' }];
|
|
11
12
|
const clearPaths = [{ d: 'M4 7h16' }, { d: 'M9 7V4h6v3' }, { d: 'm7 7 1 13h8l1-13' }];
|
|
12
13
|
const classes = (...values) => values.filter(Boolean).join(' ');
|
|
13
|
-
const defaultLabels = {
|
|
14
|
-
tagList: 'Selected tags',
|
|
15
|
-
removeTag: tag => `Remove ${tag.label ?? tag.value}`,
|
|
16
|
-
clearAll: 'Clear all tags',
|
|
17
|
-
duplicate: candidate => `${candidate} is already added.`,
|
|
18
|
-
maxTags: maximum => `You can add up to ${maximum} tags.`,
|
|
19
|
-
invalid: candidate => `${candidate} is not a valid tag.`,
|
|
20
|
-
};
|
|
21
14
|
function joinAriaIds(...values) {
|
|
22
15
|
const ids = values.flatMap(value => value?.split(/\s+/).filter(Boolean) ?? []);
|
|
23
16
|
return [...new Set(ids)].join(' ') || undefined;
|
|
24
17
|
}
|
|
25
|
-
function resolvedLabels(labels) {
|
|
18
|
+
function resolvedLabels(labels, t) {
|
|
26
19
|
return {
|
|
27
|
-
tagList: labels?.tagList ??
|
|
28
|
-
removeTag: labels?.removeTag ??
|
|
29
|
-
clearAll: labels?.clearAll ??
|
|
30
|
-
duplicate: labels?.duplicate ??
|
|
31
|
-
maxTags: labels?.maxTags ??
|
|
32
|
-
invalid: labels?.invalid ??
|
|
20
|
+
tagList: labels?.tagList ?? t('tagInput.list'),
|
|
21
|
+
removeTag: labels?.removeTag ?? (tag => t('tagInput.remove', { label: tag.label ?? tag.value })),
|
|
22
|
+
clearAll: labels?.clearAll ?? t('tagInput.clear'),
|
|
23
|
+
duplicate: labels?.duplicate ?? (label => t('tagInput.duplicate', { label })),
|
|
24
|
+
maxTags: labels?.maxTags ?? (count => t('tagInput.maximum', { count })),
|
|
25
|
+
invalid: labels?.invalid ?? (label => t('tagInput.invalid', { label })),
|
|
33
26
|
};
|
|
34
27
|
}
|
|
35
28
|
function validationText(result, fallback) {
|
|
@@ -60,7 +53,9 @@ function tagRemoveTarget(event, length) {
|
|
|
60
53
|
const index = Number(button.getAttribute('data-inkra-tag-index'));
|
|
61
54
|
return Number.isInteger(index) && index >= 0 && index < length ? { button, index } : undefined;
|
|
62
55
|
}
|
|
63
|
-
export const TagInput = forwardRef(function TagInput(
|
|
56
|
+
export const TagInput = forwardRef(function TagInput(inkraProps, forwardedRef) {
|
|
57
|
+
const { t } = useInkraLocale();
|
|
58
|
+
const { 'aria-describedby': ariaDescribedBy, 'aria-errormessage': ariaErrorMessage, 'aria-invalid': ariaInvalid, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, classNames = {}, clearable = true, createTag, defaultInputValue = '', defaultValue = [], delimiters = defaultTagInputDelimiters, disabled, form, fullWidth = true, getTagValueKey = defaultTagValueKey, id, inputProps = {}, inputValue, invalid = false, labels, maxTags, maxVisibleTags, showAllTagsLabel = count => t('tagInput.all', { count }), showFewerTagsLabel = t('tagInput.fewer'), name, onClick, onInputValueChange, onValidationError, onValueChange, placeholder, readOnly, required, seed, size = 'md', validationMessage, validateTag, value, variant = 'outline', ...rootProps } = inkraProps;
|
|
64
59
|
const generatedId = useId();
|
|
65
60
|
const inputRef = useRef(null);
|
|
66
61
|
const removeRefs = useRef(new Map());
|
|
@@ -78,7 +73,7 @@ export const TagInput = forwardRef(function TagInput({ 'aria-describedby': ariaD
|
|
|
78
73
|
const draftControlled = inputValue !== undefined;
|
|
79
74
|
const currentTags = tagsControlled ? value : uncontrolledTags;
|
|
80
75
|
const currentDraft = draftControlled ? inputValue : uncontrolledDraft;
|
|
81
|
-
const copy = useMemo(() => resolvedLabels(labels), [labels]);
|
|
76
|
+
const copy = useMemo(() => resolvedLabels(labels, t), [labels, t]);
|
|
82
77
|
const activeValidationMessage = validationMessage ?? localValidationMessage;
|
|
83
78
|
const messageId = activeValidationMessage ? `inkra-tag-input-${generatedId}-message` : undefined;
|
|
84
79
|
const state = useResolvedControlProps({
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export type InkraTheme = 'light' | 'dark' | 'auto';
|
|
3
|
+
export type InkraThemeTokens = Partial<Record<`--inkra-${string}`, string | number>>;
|
|
4
|
+
export interface ThemeProviderProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** Omit to inherit the surrounding theme. auto follows the system through CSS. */
|
|
6
|
+
theme?: InkraTheme;
|
|
7
|
+
/** Scoped CSS variables. Lengths must include units, for example "1.5px". */
|
|
8
|
+
tokens?: InkraThemeTokens;
|
|
9
|
+
}
|
|
10
|
+
/** A CSS scope: never modifies document attributes, storage or sibling themes. */
|
|
11
|
+
export declare const ThemeProvider: import("react").ForwardRefExoticComponent<ThemeProviderProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useSyncExternalStore } from 'react';
|
|
3
|
+
const forcedColorsQuery = '(forced-colors: active)';
|
|
4
|
+
function forcedColorsSnapshot() {
|
|
5
|
+
return typeof window !== 'undefined' && typeof window.matchMedia === 'function'
|
|
6
|
+
&& window.matchMedia(forcedColorsQuery).matches;
|
|
7
|
+
}
|
|
8
|
+
function subscribeForcedColors(update) {
|
|
9
|
+
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function')
|
|
10
|
+
return () => { };
|
|
11
|
+
const query = window.matchMedia(forcedColorsQuery);
|
|
12
|
+
query.addEventListener('change', update);
|
|
13
|
+
return () => query.removeEventListener('change', update);
|
|
14
|
+
}
|
|
15
|
+
const serverSnapshot = () => false;
|
|
16
|
+
/** A CSS scope: never modifies document attributes, storage or sibling themes. */
|
|
17
|
+
export const ThemeProvider = forwardRef(function ThemeProvider({ theme, tokens, style, className, children, ...props }, ref) {
|
|
18
|
+
const forcedColors = useSyncExternalStore(subscribeForcedColors, forcedColorsSnapshot, serverSnapshot);
|
|
19
|
+
const variables = Object.fromEntries(Object.entries(tokens ?? {}).filter(([key, value]) => key.startsWith('--inkra-') && (typeof value === 'string' || typeof value === 'number' && Number.isFinite(value))));
|
|
20
|
+
// Let the existing system-color tokens win over user pigments in high contrast.
|
|
21
|
+
const scopedStyle = Object.fromEntries(Object.entries({ ...variables, ...style }).filter(([key]) => !forcedColors || !key.startsWith('--inkra-')));
|
|
22
|
+
return _jsx("div", { ...props, ref: ref, className: ['inkra-theme-provider', className].filter(Boolean).join(' '), "data-theme": theme, "data-inkra-theme": theme, style: { color: 'var(--inkra-ink)', fontFamily: 'var(--inkra-font-body)', ...scopedStyle }, children: children });
|
|
23
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, memo, useCallback, useEffect, useId, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
3
4
|
import { Button, ButtonGroup } from '../Button.js';
|
|
4
5
|
import { useResolvedControlProps } from '../form/controlProps.js';
|
|
5
6
|
import { mergeAriaIds, useFieldContext } from '../form/context.js';
|
|
@@ -57,13 +58,12 @@ export const TimePicker = forwardRef(function TimePicker(allProps, forwardedRef)
|
|
|
57
58
|
const secondsVisible = showSeconds || (step !== undefined && step !== 'any' && Number(step) % 60 !== 0);
|
|
58
59
|
const resolvedStep = step ?? (secondsVisible ? 1 : 60);
|
|
59
60
|
const stepBase = String(defaultValue ?? initialValue.current);
|
|
60
|
-
const resolvedLocale = locale ?? lang
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
done: 'Apply', cancel: 'Cancel', clear: 'Clear time', invalid: 'Choose a time within the allowed range and step.' };
|
|
61
|
+
const { locale: resolvedLocale, t } = useInkraLocale(locale ?? lang, hourCycle === 'h12' ? 'en-US' : 'en-GB');
|
|
62
|
+
const copy = {
|
|
63
|
+
title: t('timePicker.title'), hour: t('timePicker.hour'), minute: t('timePicker.minute'),
|
|
64
|
+
second: t('timePicker.second'), period: t('timePicker.period'), am: t('timePicker.am'), pm: t('timePicker.pm'),
|
|
65
|
+
done: t('common.apply'), cancel: t('common.cancel'), clear: t('timePicker.clear'), invalid: t('timePicker.invalid'),
|
|
66
|
+
};
|
|
67
67
|
const currentParts = partsOf(currentValue);
|
|
68
68
|
const hasCurrentParts = currentParts !== undefined;
|
|
69
69
|
const formatter = useMemo(() => hasCurrentParts ? new Intl.DateTimeFormat(resolvedLocale, {
|
package/dist/timeline/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { forwardRef } from 'react';
|
|
3
4
|
import { PencilIcon } from '../PencilIcon.js';
|
|
4
5
|
import { PencilLine } from '../PencilLine.js';
|
|
@@ -9,7 +10,9 @@ const markerPaths = [
|
|
|
9
10
|
{ d: 'M16 11v6l4 3' },
|
|
10
11
|
];
|
|
11
12
|
const copy = (value) => typeof value === 'string' ? _jsx(PencilText, { children: value }) : value;
|
|
12
|
-
export const Timeline = forwardRef(function Timeline(
|
|
13
|
+
export const Timeline = forwardRef(function Timeline(inkraProps, ref) {
|
|
14
|
+
const { t } = useInkraLocale();
|
|
15
|
+
const { 'aria-label': ariaLabel = t('timeline.label'), className, items, orientation = 'vertical', ...props } = inkraProps;
|
|
13
16
|
return _jsx("ol", { ...props, ref: ref, "aria-label": ariaLabel, className: ['inkra-timeline', className].filter(Boolean).join(' '), "data-orientation": orientation, children: items.map((item, index) => _jsxs("li", { className: "inkra-timeline__item", children: [_jsxs("span", { className: "inkra-timeline__rail", "aria-hidden": "true", children: [_jsx(PencilSurface, { as: "span", className: "inkra-timeline__marker", variant: "quiet", radius: 8, seed: `timeline-${item.id}`, children: _jsx(PencilIcon, { paths: markerPaths, size: 24, sourceSize: 32 }) }), index < items.length - 1 && _jsx(PencilLine, { className: "inkra-timeline__connector", orientation: orientation === 'vertical' ? 'vertical' : 'horizontal', seed: `timeline-line-${item.id}` })] }), _jsxs("div", { className: "inkra-timeline__body", children: [item.dateTime
|
|
14
17
|
? _jsx("time", { className: "inkra-timeline__date", dateTime: item.dateTime, children: copy(item.date) })
|
|
15
18
|
: _jsx("span", { className: "inkra-timeline__date", children: copy(item.date) }), _jsx("div", { className: "inkra-timeline__title", children: copy(item.title) }), item.description != null && _jsx("div", { className: "inkra-timeline__description", children: copy(item.description) }), item.content != null && _jsx("div", { className: "inkra-timeline__content", children: item.content })] })] }, item.id)) });
|
package/dist/toast/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface ToastProviderProps {
|
|
|
19
19
|
viewportLabel?: string | ((placement: ToastPlacement) => string);
|
|
20
20
|
viewportClassName?: string;
|
|
21
21
|
}
|
|
22
|
-
declare function Provider(
|
|
22
|
+
declare function Provider(inkraProps: ToastProviderProps): import("react").JSX.Element;
|
|
23
23
|
export declare function useToastManager<Data extends object = any>(): {
|
|
24
24
|
toasts: ToastObject<Data>[];
|
|
25
25
|
add: <T extends Data = Data>(options: import("./manager.js").ToastAddOptions<T>) => string;
|
package/dist/toast/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { Toast as BaseToast } from '@base-ui/react/toast';
|
|
3
4
|
import { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
|
|
4
5
|
import { Button } from '../Button.js';
|
|
@@ -58,7 +59,9 @@ function ToastQueue({ closeLabel, placement, swipeDirection, viewportClassName,
|
|
|
58
59
|
return (_jsxs(BaseToast.Root, { className: "inkra-toast__root", "data-tone": tone, "data-variant": variant, "data-toast-id": toastItem.id, swipeDirection: directions, toast: toastItem, children: [_jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-toast__surface", seed: `toast-${toastItem.id}`, variant: variant === 'compact' ? 'full' : tone === 'neutral' ? 'paper' : 'quiet' }), variant === 'compact' && _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-toast__wash", seed: `toast-wash-${toastItem.id}`, variant: "selection" }), _jsx(PencilSurface, { "aria-hidden": "true", as: "span", className: "inkra-toast__focus", seed: `toast-focus-${toastItem.id}`, variant: "outline" }), _jsxs(BaseToast.Content, { className: "inkra-toast__content", children: [_jsxs("div", { className: "inkra-toast__copy", children: [toastItem.title != null && (_jsx(BaseToast.Title, { className: "inkra-toast__title", children: text(toastItem.title) })), toastItem.description != null && (_jsx(BaseToast.Description, { className: "inkra-toast__description", children: text(toastItem.description) }))] }), _jsxs("div", { className: "inkra-toast__actions", children: [toastItem.actionProps?.children != null && (_jsx(BaseToast.Action, { className: "inkra-toast__action", render: _jsx(Button, { size: "sm", variant: "outline" }) })), _jsx(BaseToast.Close, { "aria-label": closeLabel, className: "inkra-toast__close", render: _jsx(Button, { size: "icon-sm", variant: "ghost" }), children: _jsx(PencilIcon, { paths: closePaths, size: 20, sourceSize: 24, decorative: true }) })] })] })] }, toastItem.id));
|
|
59
60
|
}) }) }) }));
|
|
60
61
|
}
|
|
61
|
-
function Provider(
|
|
62
|
+
function Provider(inkraProps) {
|
|
63
|
+
const { t } = useInkraLocale();
|
|
64
|
+
const { children, closeLabel = t('toast.close'), limit, limits, placement = 'bottom-end', variant = 'auto', swipeDirection, timeout, toastManager, viewportClassName, viewportLabel = t('toast.viewport'), } = inkraProps;
|
|
62
65
|
const [localManager] = useState(() => createToastManager());
|
|
63
66
|
const manager = toastManager ?? localManager;
|
|
64
67
|
const router = getToastRouter(manager);
|
package/dist/transfer/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { forwardRef, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
3
4
|
import { Button } from '../Button.js';
|
|
4
5
|
import { Input } from '../form/Input.js';
|
|
@@ -12,29 +13,29 @@ const searchPaths = [
|
|
|
12
13
|
{ d: 'M 11 4 A 7 7 0 1 0 11 18 A 7 7 0 1 0 11 4 M 16 16 L 21 21' },
|
|
13
14
|
];
|
|
14
15
|
const rightPaths = [{ d: 'M 5 12 L 19 12 M 13 6 L 19 12 L 13 18' }];
|
|
15
|
-
const defaultLabels = {
|
|
16
|
-
sourceTitle: '
|
|
17
|
-
targetTitle: '
|
|
18
|
-
sourceSearchLabel: '
|
|
19
|
-
targetSearchLabel: '
|
|
20
|
-
sourceClearSearch: '
|
|
21
|
-
targetClearSearch: '
|
|
22
|
-
sourceSearchPlaceholder: '
|
|
23
|
-
targetSearchPlaceholder: '
|
|
24
|
-
selectAllSource: '
|
|
25
|
-
selectAllTarget: '
|
|
26
|
-
sourceEmpty: '
|
|
27
|
-
targetEmpty: '
|
|
28
|
-
sourceNoResults: '
|
|
29
|
-
targetNoResults: '
|
|
30
|
-
moveToTarget: '
|
|
31
|
-
moveToSource: '
|
|
32
|
-
moveSelectedToTarget: '
|
|
33
|
-
moveSelectedToSource: '
|
|
34
|
-
batchActions: '
|
|
35
|
-
previousPage: '
|
|
36
|
-
nextPage: '
|
|
37
|
-
};
|
|
16
|
+
const defaultLabels = (t) => ({
|
|
17
|
+
sourceTitle: t('transfer.available'),
|
|
18
|
+
targetTitle: t('common.selected'),
|
|
19
|
+
sourceSearchLabel: t('transfer.sourceSearch'),
|
|
20
|
+
targetSearchLabel: t('transfer.targetSearch'),
|
|
21
|
+
sourceClearSearch: t('transfer.sourceClear'),
|
|
22
|
+
targetClearSearch: t('transfer.targetClear'),
|
|
23
|
+
sourceSearchPlaceholder: t('transfer.sourcePlaceholder'),
|
|
24
|
+
targetSearchPlaceholder: t('transfer.targetPlaceholder'),
|
|
25
|
+
selectAllSource: t('transfer.allSource'),
|
|
26
|
+
selectAllTarget: t('transfer.allTarget'),
|
|
27
|
+
sourceEmpty: t('transfer.sourceEmpty'),
|
|
28
|
+
targetEmpty: t('transfer.targetEmpty'),
|
|
29
|
+
sourceNoResults: t('transfer.sourceNoResults'),
|
|
30
|
+
targetNoResults: t('transfer.targetNoResults'),
|
|
31
|
+
moveToTarget: t('transfer.toTarget'),
|
|
32
|
+
moveToSource: t('transfer.toSource'),
|
|
33
|
+
moveSelectedToTarget: t('transfer.selectedToTarget'),
|
|
34
|
+
moveSelectedToSource: t('transfer.selectedToSource'),
|
|
35
|
+
batchActions: t('transfer.batch'),
|
|
36
|
+
previousPage: t('common.previousPage'),
|
|
37
|
+
nextPage: t('common.nextPage'),
|
|
38
|
+
});
|
|
38
39
|
function searchableText(item) {
|
|
39
40
|
const parts = [
|
|
40
41
|
item.searchText,
|
|
@@ -52,15 +53,17 @@ function filterPanelItems(items, query, side, filterItem) {
|
|
|
52
53
|
const needle = query.trim().toLocaleLowerCase();
|
|
53
54
|
return items.filter(item => searchableText(item).includes(needle));
|
|
54
55
|
}
|
|
55
|
-
function defaultCount({ visible, total, selected }) {
|
|
56
|
-
return selected > 0 ?
|
|
56
|
+
function defaultCount({ visible, total, selected }, t) {
|
|
57
|
+
return selected > 0 ? t('transfer.count', { selected, visible, total }) : `${visible}/${total}`;
|
|
57
58
|
}
|
|
58
59
|
function itemCopy(item) {
|
|
59
60
|
return _jsxs("span", { className: "inkra-transfer__item-copy", children: [_jsx("span", { className: "inkra-transfer__item-label", children: typeof item.label === 'string' || typeof item.label === 'number'
|
|
60
61
|
? _jsx(PencilText, { children: String(item.label) })
|
|
61
62
|
: item.label }), item.description == null ? null : _jsx("span", { className: "inkra-transfer__item-description", children: item.description })] });
|
|
62
63
|
}
|
|
63
|
-
export const Transfer = forwardRef(function Transfer({ className, defaultTargetKeys = [], disabled = false, filterItem, formatCount
|
|
64
|
+
export const Transfer = forwardRef(function Transfer({ className, defaultTargetKeys = [], disabled = false, filterItem, formatCount: formatCountProp, items, labels: labelOverrides, onTargetKeysChange, pageSize, pageLabel = (page, count) => `${page} / ${count}`, renderItem, searchable = true, targetKeys, ...props }, ref) {
|
|
65
|
+
const { t } = useInkraLocale();
|
|
66
|
+
const formatCount = formatCountProp ?? ((details) => defaultCount(details, t));
|
|
64
67
|
const generatedId = useId();
|
|
65
68
|
const controlled = targetKeys !== undefined;
|
|
66
69
|
const uniqueItems = useMemo(() => uniqueTransferItems(items), [items]);
|
|
@@ -70,7 +73,7 @@ export const Transfer = forwardRef(function Transfer({ className, defaultTargetK
|
|
|
70
73
|
const currentTargetSet = useMemo(() => new Set(currentTargetKeys), [currentTargetKeys]);
|
|
71
74
|
const itemsById = useMemo(() => new Map(uniqueItems.map(item => [item.id, item])), [uniqueItems]);
|
|
72
75
|
const panels = useMemo(() => splitTransferItems(uniqueItems, currentTargetKeys), [uniqueItems, currentTargetKeys]);
|
|
73
|
-
const labels = { ...defaultLabels, ...labelOverrides };
|
|
76
|
+
const labels = { ...defaultLabels(t), ...labelOverrides };
|
|
74
77
|
const [queries, setQueries] = useState({ source: '', target: '' });
|
|
75
78
|
const [pages, setPages] = useState({ source: 0, target: 0 });
|
|
76
79
|
const pageLength = pageSize !== undefined && Number.isFinite(pageSize) ? Math.max(1, Math.floor(pageSize)) : undefined;
|
package/dist/tree/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { Tree as AriaTree, TreeItem as AriaTreeItem, TreeItemContent as AriaTreeItemContent, } from 'react-aria-components/Tree';
|
|
3
4
|
import { Button as AriaButton } from 'react-aria-components/Button';
|
|
4
5
|
import { forwardRef } from 'react';
|
|
@@ -6,14 +7,18 @@ import { PencilIcon } from '../PencilIcon.js';
|
|
|
6
7
|
import { PencilSurface } from '../PencilSurface.js';
|
|
7
8
|
import { PencilText } from '../PencilText.js';
|
|
8
9
|
const chevronIcon = [{ d: 'M 7 10 L 12 15 L 17 10' }];
|
|
9
|
-
function TreeRootInner(
|
|
10
|
+
function TreeRootInner(inkraProps, ref) {
|
|
11
|
+
const { t } = useInkraLocale();
|
|
12
|
+
const { className, style, indent = 24, size = 'md', emptyState = t('common.noItems'), selectionMode = 'single', selectionBehavior = 'toggle', ...props } = inkraProps;
|
|
10
13
|
return _jsx(AriaTree, { ...props, ref: ref, className: ['inkra-tree', className].filter(Boolean).join(' '), "data-size": size, style: { '--inkra-tree-indent': `${Number.isFinite(indent) ? Math.max(0, indent) : 24}px`, ...style }, selectionMode: selectionMode, selectionBehavior: selectionBehavior, renderEmptyState: () => _jsx("div", { className: "inkra-tree__empty", children: emptyState }) });
|
|
11
14
|
}
|
|
12
15
|
const TreeRoot = forwardRef(TreeRootInner);
|
|
13
16
|
const TreeItem = forwardRef(function TreeItem({ className, ...props }, ref) {
|
|
14
17
|
return _jsx(AriaTreeItem, { ...props, ref: ref, className: ['inkra-tree__item', className].filter(Boolean).join(' ') });
|
|
15
18
|
});
|
|
16
|
-
const TreeItemContent = forwardRef(function TreeItemContent(
|
|
19
|
+
const TreeItemContent = forwardRef(function TreeItemContent(inkraProps, ref) {
|
|
20
|
+
const { t } = useInkraLocale();
|
|
21
|
+
const { children, className, icon, disclosureIcon, expandLabel = t('tree.expand'), collapseLabel = t('tree.collapse'), } = inkraProps;
|
|
17
22
|
return _jsx(AriaTreeItemContent, { ref: ref, children: ({ hasChildItems, isExpanded, isSelected, isFocusVisible, isDisabled, level, id, }) => {
|
|
18
23
|
const state = { isExpanded, hasChildItems, isSelected, isDisabled, level };
|
|
19
24
|
const resolvedIcon = typeof icon === 'function' ? icon(state) : icon;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { forwardRef, useEffect, useId, useMemo, useRef, useState, } from 'react';
|
|
3
4
|
import { Button, ButtonGroup } from '../Button.js';
|
|
4
5
|
import { Input } from '../form/Input.js';
|
|
@@ -56,7 +57,8 @@ const TreeSelectTree = forwardRef(function TreeSelectTree({ nodes, renderLabel,
|
|
|
56
57
|
return _jsx(Tree.Root, { "aria-label": treeLabel, className: "inkra-tree-select__tree", emptyState: emptyContent, expandedKeys: effectiveExpanded, onExpandedChange: onExpandedChange, onSelectionChange: onSelectionChange, ref: ref, selectedKeys: selectedSet, selectionMode: multiple ? 'multiple' : 'single', children: treeItems });
|
|
57
58
|
});
|
|
58
59
|
export const TreeSelect = forwardRef(function TreeSelect(props, ref) {
|
|
59
|
-
const {
|
|
60
|
+
const { t } = useInkraLocale();
|
|
61
|
+
const { items, branchSelection = 'leaf', selectionPropagation = 'none', renderLabel, renderValue, placeholder = t('treeSelect.placeholder'), searchPlaceholder = t('treeSelect.search'), emptyContent = t('treeSelect.empty'), clearable = true, clearLabel = t('select.clear'), treeLabel = t('treeSelect.options'), expandLabel = t('tree.expand'), collapseLabel = t('tree.collapse'), size = 'md', name, form, disabled, readOnly, required, invalid, open: controlledOpen, defaultOpen = false, onOpenChange, expandedIds, defaultExpandedIds = [], onExpandedIdsChange, side = 'bottom', align = 'start', sideOffset = 8, collisionPadding = 8, id, className, multiple: _multiple, value: _value, defaultValue: _defaultValue, onValueChange: _onValueChange, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, ...rest } = props;
|
|
60
62
|
const field = useFieldContext();
|
|
61
63
|
const generatedId = useId();
|
|
62
64
|
const controlId = field?.controlId ?? id ?? `inkra-tree-select-${generatedId}`;
|
package/dist/upload/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
2
3
|
import { forwardRef, memo, useCallback, useEffect, useId, useMemo, useRef, useState, } from 'react';
|
|
3
4
|
import { Button } from '../Button.js';
|
|
4
5
|
import { Progress } from '../display/index.js';
|
|
@@ -10,23 +11,23 @@ const uploadPaths = [
|
|
|
10
11
|
{ d: 'm17 8-5-5-5 5' },
|
|
11
12
|
{ d: 'M12 3v12' },
|
|
12
13
|
];
|
|
13
|
-
const defaultLabels = {
|
|
14
|
-
browse: '
|
|
15
|
-
drop: '
|
|
16
|
-
selected: '
|
|
17
|
-
upload: '
|
|
18
|
-
uploading: '
|
|
19
|
-
success: '
|
|
20
|
-
error: '
|
|
21
|
-
cancelled: '
|
|
22
|
-
retry: '
|
|
23
|
-
cancel: '
|
|
24
|
-
remove: '
|
|
25
|
-
rejected: '
|
|
26
|
-
acceptError: '
|
|
27
|
-
sizeError: maxSize =>
|
|
28
|
-
countError: maxFiles =>
|
|
29
|
-
};
|
|
14
|
+
const defaultLabels = (t) => ({
|
|
15
|
+
browse: t('upload.browse'),
|
|
16
|
+
drop: t('upload.drop'),
|
|
17
|
+
selected: t('common.selected'),
|
|
18
|
+
upload: t('upload.upload'),
|
|
19
|
+
uploading: t('upload.uploading'),
|
|
20
|
+
success: t('upload.success'),
|
|
21
|
+
error: t('upload.failed'),
|
|
22
|
+
cancelled: t('upload.cancelled'),
|
|
23
|
+
retry: t('common.retry'),
|
|
24
|
+
cancel: t('common.cancel'),
|
|
25
|
+
remove: t('common.remove'),
|
|
26
|
+
rejected: t('upload.rejected'),
|
|
27
|
+
acceptError: t('upload.acceptError'),
|
|
28
|
+
sizeError: maxSize => t('upload.sizeError', { size: formatBytes(maxSize) }),
|
|
29
|
+
countError: maxFiles => t(maxFiles === 1 ? 'upload.countErrorOne' : 'upload.countError', { count: maxFiles }),
|
|
30
|
+
});
|
|
30
31
|
function formatBytes(value) {
|
|
31
32
|
if (value < 1024)
|
|
32
33
|
return `${value} B`;
|
|
@@ -60,6 +61,7 @@ const UploadRow = memo(function UploadRow({ item, labels, disabled, canUpload, s
|
|
|
60
61
|
return _jsx("li", { className: "inkra-upload__item", "data-status": item.status, children: _jsxs(PencilSurface, { className: "inkra-upload__item-surface", variant: "paper", radius: 8, children: [_jsxs("div", { className: "inkra-upload__file", children: [_jsx(PencilText, { className: "inkra-upload__name", ellipsis: true, children: item.file.name }), _jsxs("span", { className: "inkra-upload__meta", children: [formatBytes(item.file.size), " \u00B7 ", statusLabel(item.status, labels)] }), item.status === 'uploading' && _jsx(Progress, { size: "sm", value: item.progress ?? 0, "aria-label": `${item.file.name}: ${Math.round(item.progress ?? 0)}%` }), item.error && _jsx("span", { className: "inkra-upload__error", children: item.error })] }), _jsxs("div", { className: "inkra-upload__actions", children: [item.status === 'uploading' && _jsx(Button, { disabled: disabled, size: "sm", variant: "ghost", onClick: () => cancel(item.id), children: labels.cancel }), canUpload && item.status === 'selected' && _jsx(Button, { disabled: disabled, size: "sm", variant: "ghost", onClick: () => startUpload(item.id), children: labels.upload }), canUpload && (item.status === 'error' || item.status === 'cancelled') && _jsx(Button, { disabled: disabled, size: "sm", variant: "ghost", onClick: () => startUpload(item.id, 'retry'), children: labels.retry }), _jsx(Button, { disabled: disabled, size: "sm", variant: "ghost", onClick: () => remove(item.id), children: labels.remove })] })] }) });
|
|
61
62
|
});
|
|
62
63
|
export const Upload = forwardRef(function Upload({ accept, autoUpload = true, capture, className, defaultFiles = [], disabled = false, files, inputProps, labels: labelOverrides, maxFiles = Number.POSITIVE_INFINITY, maxSize = Number.POSITIVE_INFINITY, multiple = true, onFilesChange, onReject, onUpload, validate, 'aria-label': ariaLabel, ...props }, ref) {
|
|
64
|
+
const { t } = useInkraLocale();
|
|
63
65
|
const instanceId = useId();
|
|
64
66
|
const inputRef = useRef(null);
|
|
65
67
|
const itemCounter = useRef(0);
|
|
@@ -74,7 +76,8 @@ export const Upload = forwardRef(function Upload({ accept, autoUpload = true, ca
|
|
|
74
76
|
const itemsRef = useRef(items);
|
|
75
77
|
itemsRef.current = items;
|
|
76
78
|
disabledRef.current = disabled;
|
|
77
|
-
const
|
|
79
|
+
const localizedDefaults = useMemo(() => defaultLabels(t), [t]);
|
|
80
|
+
const labelValues = { ...localizedDefaults, ...labelOverrides };
|
|
78
81
|
// Snapshot scalar/function values so same-object label edits remain observable.
|
|
79
82
|
const labels = useMemo(() => labelValues, [
|
|
80
83
|
labelValues.browse, labelValues.drop, labelValues.selected, labelValues.upload,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createElement as _createElement } from "react";
|
|
3
|
+
import { useInkraLocale } from '../i18n/index.js';
|
|
3
4
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
4
5
|
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState, } from 'react';
|
|
5
6
|
import { PencilSurface } from '../PencilSurface.js';
|
|
@@ -12,7 +13,9 @@ function classes(...values) {
|
|
|
12
13
|
function toEngineScrollOptions(options) {
|
|
13
14
|
return options;
|
|
14
15
|
}
|
|
15
|
-
function VirtualListInner(
|
|
16
|
+
function VirtualListInner(inkraProps, forwardedRef) {
|
|
17
|
+
const { t } = useInkraLocale();
|
|
18
|
+
const { 'aria-label': ariaLabel, className, empty, emptyLabel = t('common.noItems'), estimateSize, gap, getItemProps, getScrollElement, height, initialOffset = 0, itemKey, items, listLabel, listRole = 'list', measureItems = false, onKeyDown, overscan, paddingEnd, paddingStart, renderItem, role: roleProp, scrollMargin, ssrItemCount, style, tabIndex, ...props } = inkraProps;
|
|
16
19
|
const rootRef = useRef(null);
|
|
17
20
|
const itemsRef = useRef(items);
|
|
18
21
|
itemsRef.current = items;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkra/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Hand-drawn React controls with native semantics and deterministic decoration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,6 +21,16 @@
|
|
|
21
21
|
"import": "./dist/index.js",
|
|
22
22
|
"default": "./dist/index.js"
|
|
23
23
|
},
|
|
24
|
+
"./theme": {
|
|
25
|
+
"types": "./dist/theme/index.d.ts",
|
|
26
|
+
"import": "./dist/theme/index.js",
|
|
27
|
+
"default": "./dist/theme/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./i18n": {
|
|
30
|
+
"types": "./dist/i18n/index.d.ts",
|
|
31
|
+
"import": "./dist/i18n/index.js",
|
|
32
|
+
"default": "./dist/i18n/index.js"
|
|
33
|
+
},
|
|
24
34
|
"./PencilSurface": {
|
|
25
35
|
"types": "./dist/PencilSurface.d.ts",
|
|
26
36
|
"import": "./dist/PencilSurface.js",
|