@homecode/ui 5.20.24 → 5.21.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/dist/esm/index.js +1 -0
- package/dist/esm/src/components/Autocomplete/Autocomplete.js +2 -0
- package/dist/esm/src/components/Gallery/Dots/Dots.js +7 -2
- package/dist/esm/src/components/Gallery/Dots/Dots.styl.js +2 -2
- package/dist/esm/src/components/InputFile/InputFile.js +2 -0
- package/dist/esm/src/components/Stepper/Stepper.js +94 -0
- package/dist/esm/src/components/Stepper/Stepper.styl.js +20 -0
- package/dist/esm/types/src/components/Gallery/Dots/Dots.d.ts +9 -4
- package/dist/esm/types/src/components/Stepper/Stepper.d.ts +3 -0
- package/dist/esm/types/src/components/Stepper/Stepper.types.d.ts +49 -0
- package/dist/esm/types/src/components/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -60,6 +60,7 @@ export { Scroll } from './src/components/Scroll/Scroll.js';
|
|
|
60
60
|
export { Slider } from './src/components/Slider/Slider.js';
|
|
61
61
|
export { Shimmer } from './src/components/Shimmer/Shimmer.js';
|
|
62
62
|
export { Spinner } from './src/components/Spinner/Spinner.js';
|
|
63
|
+
export { Stepper } from './src/components/Stepper/Stepper.js';
|
|
63
64
|
export { Table } from './src/components/Table/Table.js';
|
|
64
65
|
export { Tabs } from './src/components/Tabs/Tabs.js';
|
|
65
66
|
export { TextShimmer } from './src/components/TextShimmer/TextShimmer.js';
|
|
@@ -90,6 +90,8 @@ import '../RadioButton/RadioButton.styl.js';
|
|
|
90
90
|
import '../RadioGroup/RadioGroup.styl.js';
|
|
91
91
|
import '../Router/Router.js';
|
|
92
92
|
import '../Resizer/Resizer.styl.js';
|
|
93
|
+
import '../Gallery/Dots/Dots.styl.js';
|
|
94
|
+
import '../Stepper/Stepper.styl.js';
|
|
93
95
|
import '../Tabs/Tabs.styl.js';
|
|
94
96
|
import '../TextWithDeferTooltip/TextWithDeferTooltip.styl.js';
|
|
95
97
|
import '../Text/Text.js';
|
|
@@ -2,8 +2,13 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import S from './Dots.styl.js';
|
|
4
4
|
|
|
5
|
-
function Dots({ index, count }) {
|
|
6
|
-
return (jsx("div", { className: S.root, children: jsx("div", { className: S.inner, children: Array.from({ length: count }).map((_, i) =>
|
|
5
|
+
function Dots({ index, count, className, onSelect, getLabel, }) {
|
|
6
|
+
return (jsx("div", { className: cn(S.root, onSelect && S.interactive, className), children: jsx("div", { className: S.inner, children: Array.from({ length: count }).map((_, i) => {
|
|
7
|
+
const classes = cn(S.item, i === index && S.active);
|
|
8
|
+
if (!onSelect)
|
|
9
|
+
return jsx("div", { className: classes }, i);
|
|
10
|
+
return (jsx("button", { type: "button", className: classes, "aria-label": getLabel?.(i) ?? String(i + 1), "aria-current": i === index ? 'step' : undefined, onClick: () => onSelect(i) }, i));
|
|
11
|
+
}) }) }));
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
export { Dots as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var css_248z = ".Dots_root__dTavT{bottom:1%;display:flex;justify-content:center;-webkit-mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);overflow:hidden;padding:0 10%;pointer-events:none;position:absolute;width:100%}.Dots_inner__0Nqa9{align-items:center;display:flex}.Dots_item__gEVuS{background-color:var(--accent-color-alpha-200);border-radius:50%;box-shadow:0 0 0 1px var(--decent-color-alpha-500);flex-shrink:0;height:8px;margin:3px;transition:.1s ease-out;transition-property:background-color,transform;width:8px}.Dots_item__gEVuS.Dots_active__gAUAj{background-color:var(--accent-color-alpha-500);transform:scale(1.2)}";
|
|
2
|
-
var S = {"root":"Dots_root__dTavT","inner":"Dots_inner__0Nqa9","item":"Dots_item__gEVuS","active":"Dots_active__gAUAj"};
|
|
1
|
+
var css_248z = ".Dots_root__dTavT{bottom:1%;display:flex;justify-content:center;-webkit-mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);overflow:hidden;padding:0 10%;pointer-events:none;position:absolute;width:100%}.Dots_inner__0Nqa9{align-items:center;display:flex}.Dots_item__gEVuS{background-color:var(--accent-color-alpha-200);border-radius:50%;box-shadow:0 0 0 1px var(--decent-color-alpha-500);flex-shrink:0;height:8px;margin:3px;transition:.1s ease-out;transition-property:background-color,transform;width:8px}.Dots_item__gEVuS.Dots_active__gAUAj{background-color:var(--accent-color-alpha-500);transform:scale(1.2)}.Dots_interactive__wQylw{pointer-events:auto}.Dots_interactive__wQylw .Dots_item__gEVuS{border:none;cursor:pointer;padding:0}.Dots_interactive__wQylw .Dots_item__gEVuS:hover:not(.Dots_active__gAUAj){background-color:var(--accent-color-alpha-400)}.Dots_interactive__wQylw .Dots_item__gEVuS:focus-visible{outline:2px solid var(--active-color);outline-offset:2px}";
|
|
2
|
+
var S = {"root":"Dots_root__dTavT","inner":"Dots_inner__0Nqa9","item":"Dots_item__gEVuS","active":"Dots_active__gAUAj","interactive":"Dots_interactive__wQylw"};
|
|
3
3
|
if (typeof document !== 'undefined') {
|
|
4
4
|
var __uilibHead = document.head || document.getElementsByTagName('head')[0];
|
|
5
5
|
if (__uilibHead) {
|
|
@@ -90,6 +90,8 @@ import '../RadioButton/RadioButton.styl.js';
|
|
|
90
90
|
import '../RadioGroup/RadioGroup.styl.js';
|
|
91
91
|
import '../Router/Router.js';
|
|
92
92
|
import '../Resizer/Resizer.styl.js';
|
|
93
|
+
import '../Gallery/Dots/Dots.styl.js';
|
|
94
|
+
import '../Stepper/Stepper.styl.js';
|
|
93
95
|
import '../Tabs/Tabs.styl.js';
|
|
94
96
|
import '../TextWithDeferTooltip/TextWithDeferTooltip.styl.js';
|
|
95
97
|
import '../Text/Text.js';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useRef, useEffect } from 'react';
|
|
3
|
+
import cn from 'classnames';
|
|
4
|
+
import { Button } from '../Button/Button.js';
|
|
5
|
+
import Dots from '../Gallery/Dots/Dots.js';
|
|
6
|
+
import S from './Stepper.styl.js';
|
|
7
|
+
|
|
8
|
+
function indexOf(steps, id) {
|
|
9
|
+
const i = steps.findIndex(s => s.id === id);
|
|
10
|
+
return i < 0 ? 0 : i;
|
|
11
|
+
}
|
|
12
|
+
function textOf(node) {
|
|
13
|
+
return typeof node === 'string' || typeof node === 'number'
|
|
14
|
+
? String(node)
|
|
15
|
+
: '';
|
|
16
|
+
}
|
|
17
|
+
function Stepper({ steps, activeId, defaultActiveId, onChange, size = 'm', prevLabel = 'Prev', nextLabel = 'Next', prevButtonProps, nextButtonProps, renderPrevButton, renderNextButton, showDots = true, dotsClickable = true, renderAll = false, animation = true, className, headerClassName, contentClassName, footerClassName, }) {
|
|
18
|
+
const controlled = activeId !== undefined;
|
|
19
|
+
const [ownId, setOwnId] = useState(() => defaultActiveId ?? steps[0]?.id);
|
|
20
|
+
const currentId = controlled ? activeId : ownId;
|
|
21
|
+
const index = indexOf(steps, currentId);
|
|
22
|
+
const step = steps[index];
|
|
23
|
+
const count = steps.length;
|
|
24
|
+
// The direction of the last move, for the slide.
|
|
25
|
+
const prevIndex = useRef(index);
|
|
26
|
+
const [dir, setDir] = useState(null);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (index !== prevIndex.current) {
|
|
29
|
+
setDir(index > prevIndex.current ? 'forward' : 'back');
|
|
30
|
+
prevIndex.current = index;
|
|
31
|
+
}
|
|
32
|
+
}, [index]);
|
|
33
|
+
// A step that went away (steps changed): fall back to the nearest one.
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!controlled && step && step.id !== ownId)
|
|
36
|
+
setOwnId(step.id);
|
|
37
|
+
}, [controlled, step?.id, ownId]);
|
|
38
|
+
if (!step)
|
|
39
|
+
return null;
|
|
40
|
+
const go = (i) => {
|
|
41
|
+
const target = steps[Math.max(0, Math.min(count - 1, i))];
|
|
42
|
+
if (!target || target.id === step.id)
|
|
43
|
+
return;
|
|
44
|
+
if (!controlled)
|
|
45
|
+
setOwnId(target.id);
|
|
46
|
+
onChange?.(target.id, steps.indexOf(target));
|
|
47
|
+
};
|
|
48
|
+
const api = {
|
|
49
|
+
index,
|
|
50
|
+
count,
|
|
51
|
+
step,
|
|
52
|
+
isFirst: index === 0,
|
|
53
|
+
isLast: index === count - 1,
|
|
54
|
+
prev: () => go(index - 1),
|
|
55
|
+
next: () => go(index + 1),
|
|
56
|
+
go,
|
|
57
|
+
};
|
|
58
|
+
const button = (kind) => {
|
|
59
|
+
const own = step[kind];
|
|
60
|
+
const common = kind === 'prev' ? prevButtonProps : nextButtonProps;
|
|
61
|
+
if (own === false || (own === undefined && common === false)) {
|
|
62
|
+
return jsx("span", { className: S.placeholder });
|
|
63
|
+
}
|
|
64
|
+
const props = { ...(common || {}), ...(own || {}) };
|
|
65
|
+
const { onClick, children, ...rest } = props;
|
|
66
|
+
const isPrev = kind === 'prev';
|
|
67
|
+
// Nowhere to go and nothing else to do.
|
|
68
|
+
const stuck = isPrev ? api.isFirst : api.isLast && !onClick;
|
|
69
|
+
if (isPrev && api.isFirst && !onClick) {
|
|
70
|
+
return jsx("span", { className: S.placeholder });
|
|
71
|
+
}
|
|
72
|
+
return (jsx(Button, { round: true, size: size, variant: isPrev ? 'clear' : 'primary', disabled: stuck, ...rest, onClick: (e) => {
|
|
73
|
+
if (onClick?.(e) === false || e.defaultPrevented)
|
|
74
|
+
return;
|
|
75
|
+
if (isPrev)
|
|
76
|
+
api.prev();
|
|
77
|
+
else
|
|
78
|
+
api.next();
|
|
79
|
+
}, children: children ?? (isPrev ? prevLabel : nextLabel) }));
|
|
80
|
+
};
|
|
81
|
+
const renderContent = (s) => typeof s.content === 'function'
|
|
82
|
+
? s.content(s === step ? api : { ...api, step: s })
|
|
83
|
+
: s.content;
|
|
84
|
+
const renderStep = (s, active) => (jsxs("div", { className: cn(S.step, active && animation && dir && S[dir], !active && S.hidden), "aria-hidden": !active || undefined, children: [(s.title || s.description) && (jsxs("div", { className: cn(S.header, headerClassName), children: [s.title && jsx("div", { className: S.title, children: s.title }), s.description && (jsx("div", { className: S.description, children: s.description }))] })), jsx("div", { className: cn(S.content, contentClassName), children: renderContent(s) })] }, s.id));
|
|
85
|
+
return (jsxs("div", { className: cn(S.root, S[`size-${size}`], className), children: [jsx("div", { className: S.body, children: steps.map(s => s === step || renderAll || s.forceRender
|
|
86
|
+
? renderStep(s, s === step)
|
|
87
|
+
: null) }), jsxs("div", { className: cn(S.footer, footerClassName), children: [jsx("div", { className: S.prev, children: renderPrevButton
|
|
88
|
+
? renderPrevButton(api, button('prev'))
|
|
89
|
+
: button('prev') }), showDots && count > 1 && (jsx(Dots, { index: index, count: count, className: S.dots, onSelect: dotsClickable ? go : undefined, getLabel: i => textOf(steps[i].title) || String(i + 1) })), jsx("div", { className: S.next, children: renderNextButton
|
|
90
|
+
? renderNextButton(api, button('next'))
|
|
91
|
+
: button('next') })] })] }));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { Stepper };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
var css_248z = ".Stepper_root__WET-9{display:flex;flex-direction:column;gap:16px;min-width:0}.Stepper_body__ZRBXe{min-width:0;position:relative}.Stepper_step__e-4NN{display:flex;flex-direction:column;gap:16px;min-width:0}.Stepper_step__e-4NN.Stepper_hidden__ReHDU{display:none}.Stepper_step__e-4NN.Stepper_forward__SY8S2{animation:Stepper_stepFromRight__sFstu .22s ease-out}.Stepper_step__e-4NN.Stepper_back__ko4wh{animation:Stepper_stepFromLeft__AEIpv .22s ease-out}.Stepper_header__Hs5N2{display:flex;flex-direction:column;gap:4px}.Stepper_title__N8esM{font-size:1.4em;font-weight:600;line-height:1.2}.Stepper_description__ng-1A{line-height:1.4;opacity:.6}.Stepper_content__CTnZW{display:flex;flex-direction:column;gap:12px;min-width:0}.Stepper_footer__54ZR5{grid-gap:12px;align-items:center;display:grid;gap:12px;grid-template-columns:1fr auto 1fr}.Stepper_next__MTBhU,.Stepper_prev__eA85V{align-items:center;display:flex;gap:8px;min-width:0}.Stepper_prev__eA85V{grid-column:1;justify-self:start}.Stepper_next__MTBhU{grid-column:3;justify-self:end}.Stepper_placeholder__rpIAG{display:block}.Stepper_dots__cwSqS{grid-column:2;-webkit-mask-image:none;mask-image:none;padding:0;position:static;width:auto}.Stepper_size-s__MZtOL .Stepper_title__N8esM{font-size:1.15em}.Stepper_size-l__IP2y8 .Stepper_title__N8esM{font-size:1.7em}@media (prefers-reduced-motion:reduce){.Stepper_step__e-4NN{animation:none!important}}@keyframes Stepper_stepFromRight__sFstu{0%{opacity:0;transform:translateX(24px)}to{opacity:1;transform:none}}@keyframes Stepper_stepFromLeft__AEIpv{0%{opacity:0;transform:translateX(-24px)}to{opacity:1;transform:none}}";
|
|
2
|
+
var S = {"root":"Stepper_root__WET-9","body":"Stepper_body__ZRBXe","step":"Stepper_step__e-4NN","hidden":"Stepper_hidden__ReHDU","forward":"Stepper_forward__SY8S2","stepFromRight":"Stepper_stepFromRight__sFstu","back":"Stepper_back__ko4wh","stepFromLeft":"Stepper_stepFromLeft__AEIpv","header":"Stepper_header__Hs5N2","title":"Stepper_title__N8esM","description":"Stepper_description__ng-1A","content":"Stepper_content__CTnZW","footer":"Stepper_footer__54ZR5","prev":"Stepper_prev__eA85V","next":"Stepper_next__MTBhU","placeholder":"Stepper_placeholder__rpIAG","dots":"Stepper_dots__cwSqS","size-s":"Stepper_size-s__MZtOL","size-l":"Stepper_size-l__IP2y8"};
|
|
3
|
+
if (typeof document !== 'undefined') {
|
|
4
|
+
var __uilibHead = document.head || document.getElementsByTagName('head')[0];
|
|
5
|
+
if (__uilibHead) {
|
|
6
|
+
var __uilibStyle = document.createElement('style');
|
|
7
|
+
__uilibStyle.setAttribute('data-uilib-css', '');
|
|
8
|
+
__uilibStyle.appendChild(document.createTextNode(css_248z));
|
|
9
|
+
var __uilibLink = __uilibHead.querySelector('link[rel="stylesheet"]');
|
|
10
|
+
var __uilibInline = __uilibHead.querySelector('style:not([data-uilib-css])');
|
|
11
|
+
var __uilibAnchor = __uilibLink || __uilibInline;
|
|
12
|
+
if (__uilibLink && __uilibInline && (__uilibLink.compareDocumentPosition(__uilibInline) & 4) === 0) {
|
|
13
|
+
__uilibAnchor = __uilibInline;
|
|
14
|
+
}
|
|
15
|
+
if (__uilibAnchor) __uilibHead.insertBefore(__uilibStyle, __uilibAnchor);
|
|
16
|
+
else __uilibHead.appendChild(__uilibStyle);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { S as default };
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
index:
|
|
3
|
-
count:
|
|
4
|
-
|
|
1
|
+
type Props = {
|
|
2
|
+
index: number;
|
|
3
|
+
count: number;
|
|
4
|
+
className?: string;
|
|
5
|
+
onSelect?: (index: number) => void;
|
|
6
|
+
getLabel?: (index: number) => string;
|
|
7
|
+
};
|
|
8
|
+
export default function Dots({ index, count, className, onSelect, getLabel, }: Props): import("react").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import * as T from './Stepper.types';
|
|
2
|
+
export type { Step as StepperStep, StepButton as StepperButton, StepperApi, Props as StepperProps, } from './Stepper.types';
|
|
3
|
+
export declare function Stepper({ steps, activeId, defaultActiveId, onChange, size, prevLabel, nextLabel, prevButtonProps, nextButtonProps, renderPrevButton, renderNextButton, showDots, dotsClickable, renderAll, animation, className, headerClassName, contentClassName, footerClassName, }: T.Props): import("react").JSX.Element;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Props as ButtonProps } from '../Button/Button.types';
|
|
3
|
+
import { Size } from 'uilib/types';
|
|
4
|
+
type ID = string | number;
|
|
5
|
+
export type StepButton = false | (Omit<Partial<ButtonProps>, 'onClick'> & {
|
|
6
|
+
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => boolean | void;
|
|
7
|
+
[data: `data-${string}`]: string | undefined;
|
|
8
|
+
});
|
|
9
|
+
export type StepperApi = {
|
|
10
|
+
index: number;
|
|
11
|
+
count: number;
|
|
12
|
+
step: Step;
|
|
13
|
+
isFirst: boolean;
|
|
14
|
+
isLast: boolean;
|
|
15
|
+
prev: () => void;
|
|
16
|
+
next: () => void;
|
|
17
|
+
go: (index: number) => void;
|
|
18
|
+
};
|
|
19
|
+
export type Step = {
|
|
20
|
+
id: ID;
|
|
21
|
+
title?: ReactNode;
|
|
22
|
+
description?: ReactNode;
|
|
23
|
+
content?: ReactNode | ((api: StepperApi) => ReactNode);
|
|
24
|
+
forceRender?: boolean;
|
|
25
|
+
prev?: StepButton;
|
|
26
|
+
next?: StepButton;
|
|
27
|
+
};
|
|
28
|
+
export type Props = {
|
|
29
|
+
steps: Step[];
|
|
30
|
+
activeId?: ID;
|
|
31
|
+
defaultActiveId?: ID;
|
|
32
|
+
onChange?: (id: ID, index: number) => void;
|
|
33
|
+
size?: Size;
|
|
34
|
+
prevLabel?: ReactNode;
|
|
35
|
+
nextLabel?: ReactNode;
|
|
36
|
+
prevButtonProps?: StepButton;
|
|
37
|
+
nextButtonProps?: StepButton;
|
|
38
|
+
renderPrevButton?: (api: StepperApi, button: ReactNode) => ReactNode;
|
|
39
|
+
renderNextButton?: (api: StepperApi, button: ReactNode) => ReactNode;
|
|
40
|
+
showDots?: boolean;
|
|
41
|
+
dotsClickable?: boolean;
|
|
42
|
+
renderAll?: boolean;
|
|
43
|
+
animation?: boolean;
|
|
44
|
+
className?: string;
|
|
45
|
+
headerClassName?: string;
|
|
46
|
+
contentClassName?: string;
|
|
47
|
+
footerClassName?: string;
|
|
48
|
+
};
|
|
49
|
+
export {};
|
|
@@ -53,6 +53,7 @@ export * from './Scroll/Scroll';
|
|
|
53
53
|
export * from './Slider/Slider';
|
|
54
54
|
export * from './Shimmer/Shimmer';
|
|
55
55
|
export * from './Spinner/Spinner';
|
|
56
|
+
export * from './Stepper/Stepper';
|
|
56
57
|
export * from './Table/Table';
|
|
57
58
|
export * from './Tabs/Tabs';
|
|
58
59
|
export * from './TextShimmer/TextShimmer';
|