@hellboy/ds 0.1.2 → 0.2.7
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 +568 -71
- package/{src/style/components/badge → dist/components}/badge.css +9 -25
- package/dist/components/badge.d.mts +12 -0
- package/dist/components/badge.d.ts +12 -0
- package/dist/components/badge.js +42 -0
- package/dist/components/badge.mjs +15 -0
- package/dist/components/banner.css +280 -0
- package/dist/components/banner.d.mts +12 -0
- package/dist/components/banner.d.ts +12 -0
- package/dist/components/banner.js +184 -0
- package/dist/components/banner.mjs +147 -0
- package/dist/components/button-group.css +289 -0
- package/dist/components/button-group.d.mts +81 -0
- package/dist/components/button-group.d.ts +81 -0
- package/dist/components/button-group.js +180 -0
- package/dist/components/button-group.mjs +143 -0
- package/{src/style/components/button → dist/components}/button.css +59 -62
- package/dist/components/button.d.mts +57 -0
- package/dist/components/button.d.ts +57 -0
- package/dist/components/button.js +129 -0
- package/dist/components/button.mjs +92 -0
- package/{src/style/components/card → dist/components}/card.css +9 -30
- package/dist/components/card.d.mts +31 -0
- package/dist/components/card.d.ts +31 -0
- package/dist/components/card.js +59 -0
- package/dist/components/card.mjs +32 -0
- package/{src/style → dist}/components/checkbox.css +51 -43
- package/dist/components/checkbox.d.mts +31 -0
- package/dist/components/checkbox.d.ts +31 -0
- package/dist/components/checkbox.js +130 -0
- package/dist/components/checkbox.mjs +93 -0
- package/{src/style/components/code-block → dist/components}/code-block.css +3 -7
- package/dist/components/code-block.d.mts +24 -0
- package/dist/components/code-block.d.ts +24 -0
- package/dist/components/code-block.js +43 -0
- package/dist/components/code-block.mjs +16 -0
- package/dist/components/color-control.css +285 -0
- package/dist/components/color-control.d.mts +5 -0
- package/dist/components/color-control.d.ts +5 -0
- package/dist/components/color-control.js +534 -0
- package/dist/components/color-control.mjs +497 -0
- package/dist/components/dialog.css +930 -0
- package/dist/components/dialog.d.mts +32 -0
- package/dist/components/dialog.d.ts +32 -0
- package/dist/components/dialog.js +1111 -0
- package/dist/components/dialog.mjs +1074 -0
- package/dist/components/divider.css +356 -0
- package/dist/components/divider.d.mts +32 -0
- package/dist/components/divider.d.ts +32 -0
- package/dist/components/divider.js +344 -0
- package/dist/components/divider.mjs +307 -0
- package/{src/style/components/drag-handle → dist/components}/drag-handle.css +3 -18
- package/dist/components/drag-handle.d.mts +11 -0
- package/dist/components/drag-handle.d.ts +11 -0
- package/dist/components/drag-handle.js +103 -0
- package/dist/components/drag-handle.mjs +66 -0
- package/dist/components/drawer.css +1027 -0
- package/dist/components/drawer.d.mts +14 -0
- package/dist/components/drawer.d.ts +14 -0
- package/dist/components/drawer.js +1072 -0
- package/dist/components/drawer.mjs +1035 -0
- package/dist/components/floating-bar.css +17 -0
- package/dist/components/floating-bar.d.mts +25 -0
- package/dist/components/floating-bar.d.ts +25 -0
- package/dist/components/floating-bar.js +52 -0
- package/dist/components/floating-bar.mjs +25 -0
- package/dist/components/footer.css +40 -0
- package/dist/components/footer.d.mts +8 -0
- package/dist/components/footer.d.ts +8 -0
- package/dist/components/footer.js +44 -0
- package/dist/components/footer.mjs +17 -0
- package/dist/components/grid.css +47 -0
- package/dist/components/grid.d.mts +27 -0
- package/dist/components/grid.d.ts +27 -0
- package/dist/components/grid.js +52 -0
- package/dist/components/grid.mjs +25 -0
- package/dist/components/header.css +1075 -0
- package/dist/components/header.d.mts +35 -0
- package/dist/components/header.d.ts +35 -0
- package/dist/components/header.js +1402 -0
- package/dist/components/header.mjs +1365 -0
- package/dist/components/hero.css +121 -0
- package/dist/components/hero.d.mts +111 -0
- package/dist/components/hero.d.ts +111 -0
- package/dist/components/hero.js +285 -0
- package/dist/components/hero.mjs +248 -0
- package/{src/style/components/icons → dist/components}/icons.css +14 -15
- package/dist/components/icons.d.mts +104 -0
- package/dist/components/icons.d.ts +104 -0
- package/dist/components/icons.js +239 -0
- package/dist/components/icons.mjs +203 -0
- package/{src/style/components/input → dist/components}/input.css +189 -102
- package/dist/components/input.d.mts +114 -0
- package/dist/components/input.d.ts +114 -0
- package/dist/components/input.js +926 -0
- package/dist/components/input.mjs +879 -0
- package/dist/components/layout.css +551 -0
- package/dist/components/layout.d.mts +16 -0
- package/dist/components/layout.d.ts +16 -0
- package/dist/components/layout.js +387 -0
- package/dist/components/layout.mjs +352 -0
- package/{src/style/components/list → dist/components}/list.css +47 -41
- package/dist/components/list.d.mts +46 -0
- package/dist/components/list.d.ts +46 -0
- package/dist/components/list.js +124 -0
- package/dist/components/list.mjs +96 -0
- package/dist/components/navbar.css +706 -0
- package/dist/components/navbar.d.mts +56 -0
- package/dist/components/navbar.d.ts +56 -0
- package/dist/components/navbar.js +994 -0
- package/dist/components/navbar.mjs +952 -0
- package/{src/style/components/page-index → dist/components}/page-index.css +2 -47
- package/dist/components/page-index.d.mts +25 -0
- package/dist/components/page-index.d.ts +25 -0
- package/dist/components/page-index.js +239 -0
- package/dist/components/page-index.mjs +202 -0
- package/{src/style/components/page → dist/components}/page.css +4 -15
- package/dist/components/page.d.mts +30 -0
- package/dist/components/page.d.ts +30 -0
- package/dist/components/page.js +40 -0
- package/dist/components/page.mjs +13 -0
- package/dist/components/popover.css +87 -0
- package/dist/components/popover.d.mts +22 -0
- package/dist/components/popover.d.ts +22 -0
- package/dist/components/popover.js +243 -0
- package/dist/components/popover.mjs +206 -0
- package/{src/style → dist}/components/radio.css +8 -51
- package/dist/components/radio.d.mts +59 -0
- package/dist/components/radio.d.ts +59 -0
- package/dist/components/radio.js +133 -0
- package/dist/components/radio.mjs +95 -0
- package/dist/components/section.css +993 -0
- package/dist/components/section.d.mts +33 -0
- package/dist/components/section.d.ts +33 -0
- package/dist/components/section.js +1401 -0
- package/dist/components/section.mjs +1364 -0
- package/dist/components/select.css +391 -0
- package/dist/components/select.d.mts +63 -0
- package/dist/components/select.d.ts +63 -0
- package/dist/components/select.js +452 -0
- package/dist/components/select.mjs +415 -0
- package/{src/style/components/slider → dist/components}/slider.css +55 -33
- package/dist/components/slider.d.mts +69 -0
- package/dist/components/slider.d.ts +69 -0
- package/dist/components/slider.js +254 -0
- package/dist/components/slider.mjs +217 -0
- package/dist/components/switch.css +1081 -0
- package/dist/components/switch.d.mts +33 -0
- package/dist/components/switch.d.ts +33 -0
- package/dist/components/switch.js +1092 -0
- package/dist/components/switch.mjs +1055 -0
- package/{src/style/components/table → dist/components}/table.css +3 -28
- package/dist/components/table.d.mts +42 -0
- package/dist/components/table.d.ts +42 -0
- package/dist/components/table.js +108 -0
- package/dist/components/table.mjs +76 -0
- package/dist/components/tag.css +97 -0
- package/dist/components/tag.d.mts +12 -0
- package/dist/components/tag.d.ts +12 -0
- package/dist/components/tag.js +42 -0
- package/dist/components/tag.mjs +15 -0
- package/dist/components/textarea.css +1359 -0
- package/dist/components/textarea.d.mts +84 -0
- package/dist/components/textarea.d.ts +84 -0
- package/dist/components/textarea.js +1962 -0
- package/dist/components/textarea.mjs +1924 -0
- package/{src/style/components/theme-control → dist/components}/theme-control.css +3 -7
- package/dist/components/theme-control.d.mts +9 -0
- package/dist/components/theme-control.d.ts +9 -0
- package/dist/components/theme-control.js +235 -0
- package/dist/components/theme-control.mjs +200 -0
- package/{src/style/components/tooltip → dist/components}/tooltip.css +5 -13
- package/dist/components/tooltip.d.mts +12 -0
- package/dist/components/tooltip.d.ts +12 -0
- package/dist/components/tooltip.js +200 -0
- package/dist/components/tooltip.mjs +163 -0
- package/dist/icons-Czahnf-r.d.mts +15 -0
- package/dist/icons-Czahnf-r.d.ts +15 -0
- package/dist/index.css +2915 -2068
- package/dist/index.d.mts +144 -721
- package/dist/index.d.ts +144 -721
- package/dist/index.js +4076 -2282
- package/dist/index.mjs +4132 -2366
- package/dist/theme.css +34 -34
- package/package.json +27 -8
- package/dist/index.css.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/hellboy-ds-0.1.2.tgz +0 -0
- package/src/components/badge/Badge.tsx +0 -29
- package/src/components/badge/index.ts +0 -1
- package/src/components/banner/Banner.tsx +0 -48
- package/src/components/banner/banner.css +0 -44
- package/src/components/banner/index.ts +0 -1
- package/src/components/button/button.tsx +0 -127
- package/src/components/button/index.ts +0 -1
- package/src/components/card/card.tsx +0 -57
- package/src/components/card/index.ts +0 -1
- package/src/components/checkbox/Checkbox.tsx +0 -98
- package/src/components/checkbox/index.ts +0 -1
- package/src/components/code-block/code-block.tsx +0 -44
- package/src/components/code-block/index.ts +0 -1
- package/src/components/color-control/color-control.tsx +0 -322
- package/src/components/color-control/index.ts +0 -1
- package/src/components/drag-handle/DragHandle.tsx +0 -78
- package/src/components/drag-handle/index.ts +0 -1
- package/src/components/drawer/drawer.tsx +0 -82
- package/src/components/drawer/index.ts +0 -1
- package/src/components/floating-bar/floating-bar.tsx +0 -52
- package/src/components/floating-bar/index.ts +0 -2
- package/src/components/footer/footer.tsx +0 -28
- package/src/components/footer/index.ts +0 -1
- package/src/components/grid/Grid.tsx +0 -53
- package/src/components/grid/index.ts +0 -1
- package/src/components/header/header.tsx +0 -57
- package/src/components/header/index.ts +0 -1
- package/src/components/icons/icons.tsx +0 -44
- package/src/components/icons/index.ts +0 -1
- package/src/components/index.ts +0 -29
- package/src/components/input/DatePicker.tsx +0 -133
- package/src/components/input/Input.tsx +0 -220
- package/src/components/input/InputDate.tsx +0 -10
- package/src/components/input/InputDateTime.tsx +0 -10
- package/src/components/input/InputEmail.tsx +0 -10
- package/src/components/input/InputField.tsx +0 -137
- package/src/components/input/InputNumber.tsx +0 -10
- package/src/components/input/InputPassword.tsx +0 -10
- package/src/components/input/InputSearch.tsx +0 -10
- package/src/components/input/InputTel.tsx +0 -10
- package/src/components/input/InputText.tsx +0 -10
- package/src/components/input/InputTime.tsx +0 -10
- package/src/components/input/InputUrl.tsx +0 -10
- package/src/components/input/TimePicker.tsx +0 -151
- package/src/components/input/index.ts +0 -11
- package/src/components/layout/Layout.tsx +0 -244
- package/src/components/layout/index.ts +0 -1
- package/src/components/list/List.tsx +0 -159
- package/src/components/list/index.ts +0 -1
- package/src/components/navbar/MenuCategory.tsx +0 -20
- package/src/components/navbar/MenuGroup.tsx +0 -288
- package/src/components/navbar/MenuItem.tsx +0 -65
- package/src/components/navbar/Navbar.tsx +0 -23
- package/src/components/navbar/index.ts +0 -4
- package/src/components/page/index.ts +0 -1
- package/src/components/page/page.tsx +0 -46
- package/src/components/page-index/PageIndex.tsx +0 -275
- package/src/components/page-index/index.ts +0 -1
- package/src/components/popover/index.ts +0 -1
- package/src/components/popover/popover.tsx +0 -199
- package/src/components/radio/Radio.tsx +0 -176
- package/src/components/radio/index.ts +0 -1
- package/src/components/section/index.ts +0 -1
- package/src/components/section/section.tsx +0 -66
- package/src/components/select/Select.tsx +0 -212
- package/src/components/select/index.ts +0 -1
- package/src/components/slider/Slider.tsx +0 -267
- package/src/components/slider/index.ts +0 -1
- package/src/components/switch/index.ts +0 -1
- package/src/components/switch/switch.tsx +0 -99
- package/src/components/table/Table.tsx +0 -147
- package/src/components/table/index.ts +0 -1
- package/src/components/theme-control/index.ts +0 -1
- package/src/components/theme-control/theme-control.tsx +0 -78
- package/src/components/tooltip/index.ts +0 -1
- package/src/components/tooltip/tooltip.tsx +0 -207
- package/src/contexts/NavbarTooltipContext.tsx +0 -48
- package/src/contexts/index.ts +0 -1
- package/src/foundations/motion.md +0 -136
- package/src/index.ts +0 -40
- package/src/style/_shared/field.css +0 -69
- package/src/style/components/color-control/color-control.css +0 -126
- package/src/style/components/drawer/drawer.css +0 -210
- package/src/style/components/floating-bar/floating-bar.css +0 -39
- package/src/style/components/footer/footer.css +0 -108
- package/src/style/components/grid/grid.css +0 -33
- package/src/style/components/header/header.css +0 -44
- package/src/style/components/layout/layout.css +0 -205
- package/src/style/components/navbar/navbar.css +0 -342
- package/src/style/components/popover/popover.css +0 -44
- package/src/style/components/section/section.css +0 -67
- package/src/style/components/select/select.css +0 -143
- package/src/style/components/switch/switch.css +0 -267
- package/src/style/foundations/global.css +0 -316
- package/src/style/foundations/motion.css +0 -164
- package/src/style/foundations/spacing.css +0 -51
- package/src/style/foundations/typography.css +0 -39
- package/src/style/foundations/z-index.css +0 -81
- package/src/style/modes/dark.css +0 -146
- package/src/style/modes/light.css +0 -147
- package/src/style/semantic.css +0 -52
- package/src/style/styles.css +0 -51
- package/src/style/themes/theme.json +0 -37
- package/src/utils/README.md +0 -305
- package/src/utils/USER_PREFERENCES.md +0 -558
- package/src/utils/theme.ts +0 -127
- package/src/utils/user-preferences.ts +0 -577
- package/tsconfig.json +0 -25
- package/tsup.config.ts +0 -52
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
interface TimePickerProps {
|
|
4
|
-
value: string;
|
|
5
|
-
onChange: (value: string) => void;
|
|
6
|
-
disabled?: boolean;
|
|
7
|
-
showMilliseconds?: boolean;
|
|
8
|
-
minuteStep?: 1 | 5 | 15 | 30;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const parseTime = (timeStr: string) => {
|
|
12
|
-
if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
|
|
13
|
-
const parts = timeStr.split(':');
|
|
14
|
-
const hours = parseInt(parts[0] || '0', 10);
|
|
15
|
-
const minutes = parseInt(parts[1] || '0', 10);
|
|
16
|
-
const secondsParts = (parts[2] || '0').split('.');
|
|
17
|
-
const seconds = parseInt(secondsParts[0] || '0', 10);
|
|
18
|
-
const milliseconds = parseInt(secondsParts[1] || '0', 10);
|
|
19
|
-
return { hours, minutes, seconds, milliseconds };
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
interface TimeColumnProps {
|
|
23
|
-
label: string;
|
|
24
|
-
value: number;
|
|
25
|
-
max: number;
|
|
26
|
-
field: 'hours' | 'minutes' | 'seconds' | 'milliseconds';
|
|
27
|
-
step: number;
|
|
28
|
-
disabled?: boolean;
|
|
29
|
-
onChange: (field: 'hours' | 'minutes' | 'seconds' | 'milliseconds', value: number) => void;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const TimeColumn: React.FC<TimeColumnProps> = ({
|
|
33
|
-
label,
|
|
34
|
-
value,
|
|
35
|
-
max,
|
|
36
|
-
field,
|
|
37
|
-
step,
|
|
38
|
-
disabled,
|
|
39
|
-
onChange
|
|
40
|
-
}) => {
|
|
41
|
-
const items = Array.from({ length: Math.floor(max / step) + 1 }, (_, i) => i * step);
|
|
42
|
-
const columnRef = React.useRef<HTMLDivElement>(null);
|
|
43
|
-
|
|
44
|
-
React.useEffect(() => {
|
|
45
|
-
if (columnRef.current) {
|
|
46
|
-
const selected = columnRef.current.querySelector('.time-picker__item--selected');
|
|
47
|
-
if (selected) {
|
|
48
|
-
selected.scrollIntoView({ block: 'center', behavior: 'smooth' });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}, [value]);
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<div className="time-picker__column">
|
|
55
|
-
<div className="time-picker__label">{label}</div>
|
|
56
|
-
<div className="time-picker__scroll" ref={columnRef}>
|
|
57
|
-
{items.map(item => (
|
|
58
|
-
<button
|
|
59
|
-
key={item}
|
|
60
|
-
type="button"
|
|
61
|
-
className={`time-picker__item ${item === value ? 'time-picker__item--selected' : ''}`}
|
|
62
|
-
onClick={() => onChange(field, item)}
|
|
63
|
-
disabled={disabled}
|
|
64
|
-
>
|
|
65
|
-
{String(item).padStart(field === 'milliseconds' ? 3 : 2, '0')}
|
|
66
|
-
</button>
|
|
67
|
-
))}
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export const TimePicker: React.FC<TimePickerProps> = ({
|
|
74
|
-
value,
|
|
75
|
-
onChange,
|
|
76
|
-
disabled,
|
|
77
|
-
showMilliseconds = false,
|
|
78
|
-
minuteStep = 1
|
|
79
|
-
}) => {
|
|
80
|
-
// Manter estado interno dos valores para evitar perder seleções
|
|
81
|
-
const [internalTime, setInternalTime] = React.useState(value);
|
|
82
|
-
|
|
83
|
-
// Sincronizar estado interno quando o valor prop muda
|
|
84
|
-
React.useEffect(() => {
|
|
85
|
-
setInternalTime(value);
|
|
86
|
-
}, [value]);
|
|
87
|
-
|
|
88
|
-
const { hours, minutes, seconds, milliseconds } = parseTime(internalTime);
|
|
89
|
-
|
|
90
|
-
const handleChange = (field: 'hours' | 'minutes' | 'seconds' | 'milliseconds', newValue: number) => {
|
|
91
|
-
if (disabled) return;
|
|
92
|
-
|
|
93
|
-
const currentParsed = parseTime(internalTime);
|
|
94
|
-
const updated = { ...currentParsed, [field]: newValue };
|
|
95
|
-
|
|
96
|
-
let formattedTime = `${String(updated.hours).padStart(2, '0')}:${String(updated.minutes).padStart(2, '0')}:${String(updated.seconds).padStart(2, '0')}`;
|
|
97
|
-
|
|
98
|
-
if (showMilliseconds && updated.milliseconds > 0) {
|
|
99
|
-
formattedTime += `.${String(updated.milliseconds).padStart(3, '0')}`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Atualizar estado interno imediatamente
|
|
103
|
-
setInternalTime(formattedTime);
|
|
104
|
-
// E notificar o componente pai
|
|
105
|
-
onChange(formattedTime);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<div className="time-picker">
|
|
110
|
-
<TimeColumn
|
|
111
|
-
label="Hours"
|
|
112
|
-
value={hours}
|
|
113
|
-
max={23}
|
|
114
|
-
field="hours"
|
|
115
|
-
step={1}
|
|
116
|
-
disabled={disabled}
|
|
117
|
-
onChange={handleChange}
|
|
118
|
-
/>
|
|
119
|
-
<TimeColumn
|
|
120
|
-
label="Minutes"
|
|
121
|
-
value={minutes}
|
|
122
|
-
max={59}
|
|
123
|
-
field="minutes"
|
|
124
|
-
step={minuteStep}
|
|
125
|
-
disabled={disabled}
|
|
126
|
-
onChange={handleChange}
|
|
127
|
-
/>
|
|
128
|
-
<TimeColumn
|
|
129
|
-
label="Seconds"
|
|
130
|
-
value={seconds}
|
|
131
|
-
max={59}
|
|
132
|
-
field="seconds"
|
|
133
|
-
step={1}
|
|
134
|
-
disabled={disabled}
|
|
135
|
-
onChange={handleChange}
|
|
136
|
-
/>
|
|
137
|
-
{showMilliseconds && (
|
|
138
|
-
<TimeColumn
|
|
139
|
-
label="ms"
|
|
140
|
-
value={milliseconds}
|
|
141
|
-
max={999}
|
|
142
|
-
field="milliseconds"
|
|
143
|
-
step={1}
|
|
144
|
-
disabled={disabled}
|
|
145
|
-
onChange={handleChange}
|
|
146
|
-
/>
|
|
147
|
-
)}
|
|
148
|
-
</div>
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Individual input components for tree-shaking
|
|
2
|
-
export { InputText, type InputTextProps } from './InputText';
|
|
3
|
-
export { InputEmail, type InputEmailProps } from './InputEmail';
|
|
4
|
-
export { InputPassword, type InputPasswordProps } from './InputPassword';
|
|
5
|
-
export { InputSearch, type InputSearchProps } from './InputSearch';
|
|
6
|
-
export { InputTel, type InputTelProps } from './InputTel';
|
|
7
|
-
export { InputUrl, type InputUrlProps } from './InputUrl';
|
|
8
|
-
export { InputNumber, type InputNumberProps } from './InputNumber';
|
|
9
|
-
export { InputDate, type InputDateProps } from './InputDate';
|
|
10
|
-
export { InputTime, type InputTimeProps } from './InputTime';
|
|
11
|
-
export { InputDateTime, type InputDateTimeProps } from './InputDateTime';
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { DragHandle } from "../drag-handle";
|
|
3
|
-
import { getPreference, setPreference } from "../../utils/user-preferences";
|
|
4
|
-
import "../../style/components/layout/layout.css";
|
|
5
|
-
|
|
6
|
-
export type LayoutVariant = "single" | "stacked" | "sidebar-main-sidebar";
|
|
7
|
-
|
|
8
|
-
export interface LayoutProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
9
|
-
variant?: LayoutVariant;
|
|
10
|
-
header?: React.ReactNode;
|
|
11
|
-
footer?: React.ReactNode;
|
|
12
|
-
sidebarLeft?: React.ReactNode;
|
|
13
|
-
sidebarRight?: React.ReactNode;
|
|
14
|
-
bottomBar?: React.ReactNode;
|
|
15
|
-
resizable?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const Layout: React.FC<LayoutProps> = ({
|
|
19
|
-
variant = "stacked",
|
|
20
|
-
header,
|
|
21
|
-
footer,
|
|
22
|
-
sidebarLeft,
|
|
23
|
-
sidebarRight,
|
|
24
|
-
bottomBar,
|
|
25
|
-
resizable = false,
|
|
26
|
-
children,
|
|
27
|
-
className = "",
|
|
28
|
-
...props
|
|
29
|
-
}) => {
|
|
30
|
-
const classes = ["layout", `layout--${variant}`, className].filter(Boolean).join(" ");
|
|
31
|
-
|
|
32
|
-
// Navbar constants
|
|
33
|
-
const NAVBAR_COLLAPSED_WIDTH = 72;
|
|
34
|
-
const NAVBAR_EXPAND_THRESHOLD = 210;
|
|
35
|
-
const NAVBAR_MIN_PERSIST_WIDTH = 211; // 210 + 1 to avoid auto-collapse threshold
|
|
36
|
-
const NAVBAR_MAX_WIDTH = 600;
|
|
37
|
-
|
|
38
|
-
const hasSidebarLeft = sidebarLeft != null;
|
|
39
|
-
const hasSidebarRight = sidebarRight != null;
|
|
40
|
-
const sidebarLeftIsNavbar = hasSidebarLeft && React.isValidElement(sidebarLeft) && Boolean((sidebarLeft as any).props?.isNavbar);
|
|
41
|
-
const columnCount = [hasSidebarLeft, true, hasSidebarRight].filter(Boolean).length;
|
|
42
|
-
const shouldShowResizers = resizable && columnCount >= 2;
|
|
43
|
-
|
|
44
|
-
// State for sidebar widths with preference persistence
|
|
45
|
-
const [leftSidebarWidth, setLeftSidebarWidth] = React.useState<number>(() => {
|
|
46
|
-
const v = getPreference<number>('layout.leftSidebarWidth', 280);
|
|
47
|
-
return typeof v === 'number' ? v : 280;
|
|
48
|
-
});
|
|
49
|
-
// read preferred expanded width (user configured). We keep this separate
|
|
50
|
-
// from the current effective width so collapsing (72) doesn't overwrite it.
|
|
51
|
-
const preferredLeftSidebarWidth = React.useMemo<number>(() => {
|
|
52
|
-
const v = getPreference<number>('layout.leftSidebarPreferredWidth', leftSidebarWidth);
|
|
53
|
-
// Only return valid preferred widths (>= 211px)
|
|
54
|
-
if (typeof v === 'number' && v >= NAVBAR_MIN_PERSIST_WIDTH) {
|
|
55
|
-
return v;
|
|
56
|
-
}
|
|
57
|
-
// Fallback to a safe default
|
|
58
|
-
return Math.max(NAVBAR_MIN_PERSIST_WIDTH, leftSidebarWidth);
|
|
59
|
-
}, [leftSidebarWidth]);
|
|
60
|
-
const [rightSidebarWidth, setRightSidebarWidth] = React.useState<number>(() => {
|
|
61
|
-
const v = getPreference<number>('layout.rightSidebarWidth', 300);
|
|
62
|
-
return typeof v === 'number' ? v : 300;
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const clampLeftWidth = React.useCallback((width: number) => {
|
|
66
|
-
console.log('clampLeftWidth called with:', width);
|
|
67
|
-
// allow collapsed width 72; otherwise enforce expanded min 72 and max 600
|
|
68
|
-
// Remove the 128px minimum limitation to allow smoother transitions
|
|
69
|
-
if (width <= NAVBAR_COLLAPSED_WIDTH) {
|
|
70
|
-
console.log('Returning 72 (collapsed)');
|
|
71
|
-
return NAVBAR_COLLAPSED_WIDTH;
|
|
72
|
-
}
|
|
73
|
-
const result = Math.max(NAVBAR_COLLAPSED_WIDTH, Math.min(NAVBAR_MAX_WIDTH, Math.round(width)));
|
|
74
|
-
console.log('Returning clamped result:', result);
|
|
75
|
-
return result;
|
|
76
|
-
}, []);
|
|
77
|
-
|
|
78
|
-
const updateLeftSidebarWidth = React.useCallback((width: number) => {
|
|
79
|
-
console.log('updateLeftSidebarWidth called with:', width);
|
|
80
|
-
const newWidth = clampLeftWidth(width);
|
|
81
|
-
console.log('clampLeftWidth result:', newWidth);
|
|
82
|
-
setLeftSidebarWidth(newWidth);
|
|
83
|
-
// Only persist if width is valid (>= 211px)
|
|
84
|
-
if (newWidth >= NAVBAR_MIN_PERSIST_WIDTH) {
|
|
85
|
-
setPreference('layout.leftSidebarWidth', newWidth);
|
|
86
|
-
}
|
|
87
|
-
}, [clampLeftWidth]);
|
|
88
|
-
|
|
89
|
-
const handleLeftResize = React.useCallback((delta: number) => {
|
|
90
|
-
setLeftSidebarWidth((prev = 300) => {
|
|
91
|
-
const newWidthRaw = prev + delta;
|
|
92
|
-
const newWidth = clampLeftWidth(newWidthRaw);
|
|
93
|
-
|
|
94
|
-
// Only persist widths >= 211px to avoid storing invalid values that would cause auto-collapse
|
|
95
|
-
if (newWidth >= NAVBAR_MIN_PERSIST_WIDTH) {
|
|
96
|
-
setPreference('layout.leftSidebarWidth', newWidth);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Auto-collapse during drag only if the delta is significant (avoid micro-movements)
|
|
100
|
-
if (sidebarLeftIsNavbar && Math.abs(delta) > 5 && newWidth < NAVBAR_EXPAND_THRESHOLD) {
|
|
101
|
-
setPreference('layout.leftSidebarWidth', NAVBAR_COLLAPSED_WIDTH);
|
|
102
|
-
return NAVBAR_COLLAPSED_WIDTH;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// when user resizes to expanded widths (>=211) we also update the preferred width
|
|
106
|
-
if (newWidth >= NAVBAR_MIN_PERSIST_WIDTH) {
|
|
107
|
-
setPreference('layout.leftSidebarPreferredWidth', newWidth);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return newWidth;
|
|
111
|
-
});
|
|
112
|
-
}, [clampLeftWidth, sidebarLeftIsNavbar]);
|
|
113
|
-
|
|
114
|
-
const handleLeftResizeEnd = React.useCallback(() => {
|
|
115
|
-
setLeftSidebarWidth((currentWidth) => {
|
|
116
|
-
if (currentWidth < NAVBAR_EXPAND_THRESHOLD) {
|
|
117
|
-
// collapse to navbar width (72px) when below 210px
|
|
118
|
-
const collapsed = NAVBAR_COLLAPSED_WIDTH;
|
|
119
|
-
setPreference('layout.leftSidebarWidth', collapsed);
|
|
120
|
-
return collapsed;
|
|
121
|
-
}
|
|
122
|
-
return currentWidth;
|
|
123
|
-
});
|
|
124
|
-
}, []);
|
|
125
|
-
|
|
126
|
-
const handleRightResize = React.useCallback((delta: number) => {
|
|
127
|
-
setRightSidebarWidth((prev = 300) => {
|
|
128
|
-
const newWidth = Math.max(200, Math.min(600, prev - delta));
|
|
129
|
-
setPreference('layout.rightSidebarWidth', newWidth);
|
|
130
|
-
return newWidth;
|
|
131
|
-
});
|
|
132
|
-
}, []);
|
|
133
|
-
|
|
134
|
-
if (variant === "single") {
|
|
135
|
-
return (
|
|
136
|
-
<div className={classes} {...props}>
|
|
137
|
-
<div className="layout__container">
|
|
138
|
-
<main className="layout__main">
|
|
139
|
-
{header && <header className="layout__header">{header}</header>}
|
|
140
|
-
{children}
|
|
141
|
-
{footer && <footer className="layout__footer">{footer}</footer>}
|
|
142
|
-
</main>
|
|
143
|
-
{bottomBar && <div className="layout__bottom-bar">{bottomBar}</div>}
|
|
144
|
-
</div>
|
|
145
|
-
</div>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (variant === "stacked") {
|
|
150
|
-
return (
|
|
151
|
-
<div className={classes} {...props}>
|
|
152
|
-
<div className="layout__container">
|
|
153
|
-
<main className="layout__main">
|
|
154
|
-
{header && <header className="layout__header">{header}</header>}
|
|
155
|
-
{children}
|
|
156
|
-
{footer && <footer className="layout__footer">{footer}</footer>}
|
|
157
|
-
</main>
|
|
158
|
-
{bottomBar && <div className="layout__bottom-bar">{bottomBar}</div>}
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (variant === "sidebar-main-sidebar") {
|
|
165
|
-
return (
|
|
166
|
-
<div className={classes} {...props}>
|
|
167
|
-
{hasSidebarLeft && (
|
|
168
|
-
<>
|
|
169
|
-
<aside
|
|
170
|
-
className="layout__sidebar layout__sidebar--left"
|
|
171
|
-
style={{ width: leftSidebarWidth }}
|
|
172
|
-
>
|
|
173
|
-
{React.isValidElement(sidebarLeft)
|
|
174
|
-
? React.cloneElement(sidebarLeft as React.ReactElement, {
|
|
175
|
-
sidebarWidth: leftSidebarWidth,
|
|
176
|
-
setSidebarWidth: updateLeftSidebarWidth,
|
|
177
|
-
preferredSidebarWidth: preferredLeftSidebarWidth,
|
|
178
|
-
setPreferredSidebarWidth: (w: number) => {
|
|
179
|
-
const newW = clampLeftWidth(w);
|
|
180
|
-
// Only persist preferred widths >= 211px
|
|
181
|
-
if (newW >= NAVBAR_MIN_PERSIST_WIDTH) {
|
|
182
|
-
setPreference('layout.leftSidebarPreferredWidth', newW);
|
|
183
|
-
}
|
|
184
|
-
// if currently expanded, also apply
|
|
185
|
-
if (leftSidebarWidth > NAVBAR_COLLAPSED_WIDTH) {
|
|
186
|
-
setLeftSidebarWidth(newW);
|
|
187
|
-
setPreference('layout.leftSidebarWidth', newW);
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
})
|
|
191
|
-
: sidebarLeft}
|
|
192
|
-
</aside>
|
|
193
|
-
{shouldShowResizers && (
|
|
194
|
-
<DragHandle
|
|
195
|
-
orientation="vertical"
|
|
196
|
-
onResize={handleLeftResize}
|
|
197
|
-
onResizeEnd={handleLeftResizeEnd}
|
|
198
|
-
/>
|
|
199
|
-
)}
|
|
200
|
-
</>
|
|
201
|
-
)}
|
|
202
|
-
<div className="layout__container">
|
|
203
|
-
<main className="layout__main">
|
|
204
|
-
{header && <header className="layout__header">{header}</header>}
|
|
205
|
-
{children}
|
|
206
|
-
{footer && <footer className="layout__footer">{footer}</footer>}
|
|
207
|
-
</main>
|
|
208
|
-
{bottomBar && <div className="layout__bottom-bar">{bottomBar}</div>}
|
|
209
|
-
</div>
|
|
210
|
-
{hasSidebarRight && (
|
|
211
|
-
<>
|
|
212
|
-
{shouldShowResizers && (
|
|
213
|
-
<DragHandle
|
|
214
|
-
orientation="vertical"
|
|
215
|
-
onResize={handleRightResize}
|
|
216
|
-
/>
|
|
217
|
-
)}
|
|
218
|
-
<aside
|
|
219
|
-
className="layout__sidebar layout__sidebar--right"
|
|
220
|
-
style={{ width: rightSidebarWidth }}
|
|
221
|
-
>
|
|
222
|
-
{React.isValidElement(sidebarRight)
|
|
223
|
-
? React.cloneElement(sidebarRight as React.ReactElement, {
|
|
224
|
-
sidebarWidth: rightSidebarWidth,
|
|
225
|
-
setSidebarWidth: (w: number) => {
|
|
226
|
-
const newW = Math.max(200, Math.min(600, w));
|
|
227
|
-
setRightSidebarWidth(newW);
|
|
228
|
-
setPreference('layout.rightSidebarWidth', newW);
|
|
229
|
-
},
|
|
230
|
-
})
|
|
231
|
-
: sidebarRight}
|
|
232
|
-
</aside>
|
|
233
|
-
</>
|
|
234
|
-
)}
|
|
235
|
-
</div>
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return (
|
|
240
|
-
<div className={classes} {...props}>
|
|
241
|
-
{children}
|
|
242
|
-
</div>
|
|
243
|
-
);
|
|
244
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Layout, type LayoutProps, type LayoutVariant } from './Layout';
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Icon } from '../icons/icons';
|
|
3
|
-
import '../../style/components/list/list.css';
|
|
4
|
-
|
|
5
|
-
export interface ListItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
|
-
/**
|
|
7
|
-
* Item content
|
|
8
|
-
*/
|
|
9
|
-
children: React.ReactNode;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Icon name from our icon library
|
|
13
|
-
*/
|
|
14
|
-
icon?: string;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Whether the item is selected
|
|
18
|
-
*/
|
|
19
|
-
selected?: boolean;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Whether the item is disabled
|
|
23
|
-
*/
|
|
24
|
-
disabled?: boolean;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Click handler
|
|
28
|
-
*/
|
|
29
|
-
onClick?: () => void;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Custom class name
|
|
33
|
-
*/
|
|
34
|
-
className?: string;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Category label for organizing items (display only)
|
|
38
|
-
*/
|
|
39
|
-
category?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface ListCategoryProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
43
|
-
/**
|
|
44
|
-
* Category title
|
|
45
|
-
*/
|
|
46
|
-
title: string;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Category items
|
|
50
|
-
*/
|
|
51
|
-
children: React.ReactNode;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Custom class name
|
|
55
|
-
*/
|
|
56
|
-
className?: string;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const ListItem: React.FC<ListItemProps> = ({
|
|
60
|
-
children,
|
|
61
|
-
icon,
|
|
62
|
-
selected = false,
|
|
63
|
-
disabled = false,
|
|
64
|
-
onClick,
|
|
65
|
-
category,
|
|
66
|
-
className = '',
|
|
67
|
-
...props
|
|
68
|
-
}) => {
|
|
69
|
-
const classes = [
|
|
70
|
-
'list-item',
|
|
71
|
-
selected && 'list-item--selected',
|
|
72
|
-
disabled && 'list-item--disabled',
|
|
73
|
-
onClick && !disabled && 'list-item--interactive',
|
|
74
|
-
className,
|
|
75
|
-
]
|
|
76
|
-
.filter(Boolean)
|
|
77
|
-
.join(' ');
|
|
78
|
-
|
|
79
|
-
const handleClick = () => {
|
|
80
|
-
if (!disabled && onClick) {
|
|
81
|
-
onClick();
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
86
|
-
if (!disabled && onClick && (e.key === 'Enter' || e.key === ' ')) {
|
|
87
|
-
e.preventDefault();
|
|
88
|
-
onClick();
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<div
|
|
94
|
-
className={classes}
|
|
95
|
-
onClick={handleClick}
|
|
96
|
-
onKeyDown={handleKeyDown}
|
|
97
|
-
role={onClick ? 'button' : undefined}
|
|
98
|
-
tabIndex={onClick && !disabled ? 0 : undefined}
|
|
99
|
-
aria-selected={selected}
|
|
100
|
-
aria-disabled={disabled}
|
|
101
|
-
{...props}
|
|
102
|
-
>
|
|
103
|
-
{icon && (
|
|
104
|
-
<div className="list-item__icon">
|
|
105
|
-
<Icon name={icon} size={20} />
|
|
106
|
-
</div>
|
|
107
|
-
)}
|
|
108
|
-
<div className="list-item__content">
|
|
109
|
-
{category && <div className="list-item__category">{category}</div>}
|
|
110
|
-
<div>{children}</div>
|
|
111
|
-
</div>
|
|
112
|
-
{selected && (
|
|
113
|
-
<div className="list-item__indicator">
|
|
114
|
-
<Icon name="checkmark" size={16} />
|
|
115
|
-
</div>
|
|
116
|
-
)}
|
|
117
|
-
</div>
|
|
118
|
-
);
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export const ListCategory: React.FC<ListCategoryProps> = ({
|
|
122
|
-
title,
|
|
123
|
-
children,
|
|
124
|
-
className = '',
|
|
125
|
-
...props
|
|
126
|
-
}) => {
|
|
127
|
-
const classes = ['list-category', className].filter(Boolean).join(' ');
|
|
128
|
-
|
|
129
|
-
return (
|
|
130
|
-
<div className={classes} {...props}>
|
|
131
|
-
<div className="list-category__title">{title}</div>
|
|
132
|
-
<div className="list-category__items">
|
|
133
|
-
{children}
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export interface ListProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
140
|
-
/**
|
|
141
|
-
* List items
|
|
142
|
-
*/
|
|
143
|
-
children: React.ReactNode;
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Custom class name
|
|
147
|
-
*/
|
|
148
|
-
className?: string;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export const List: React.FC<ListProps> = ({ children, className = '', ...props }) => {
|
|
152
|
-
const classes = ['list', className].filter(Boolean).join(' ');
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<div className={classes} role="list" {...props}>
|
|
156
|
-
{children}
|
|
157
|
-
</div>
|
|
158
|
-
);
|
|
159
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { List, ListItem, type ListProps, type ListItemProps } from './List';
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
export interface MenuCategoryProps {
|
|
4
|
-
title: string;
|
|
5
|
-
children: React.ReactNode;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const MenuCategory: React.FC<MenuCategoryProps> = ({
|
|
9
|
-
title,
|
|
10
|
-
children
|
|
11
|
-
}) => {
|
|
12
|
-
return (
|
|
13
|
-
<div className="navbar__menu-category">
|
|
14
|
-
<div className="navbar__menu-category-title">{title}</div>
|
|
15
|
-
<div className="navbar__menu-category-content">
|
|
16
|
-
{children}
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
);
|
|
20
|
-
};
|