@orcestr/ui 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/README.ru.md +4 -0
- package/dist/example/ExampleThemePlayground.d.ts +29 -29
- package/dist/example/ExampleThemePlayground.js +29 -29
- package/dist/example/UiExamplePage.d.ts +7 -1
- package/dist/example/UiExamplePage.d.ts.map +1 -1
- package/dist/example/UiExamplePage.js +33 -17
- package/dist/styles/orcestr-ui.css +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
# Orcestr UI
|
|
12
12
|
|
|
13
|
+
## [Demo](https://orcestr.com/ui)
|
|
14
|
+
|
|
15
|
+
Open the live example page to inspect Orcestr UI components and patterns in context.
|
|
16
|
+
|
|
13
17
|
Shared React UI foundation for Orcestr products.
|
|
14
18
|
|
|
15
19
|
Orcestr UI is a public component library extracted from real Orcestr product work. It collects the interface primitives we reuse across product surfaces: app shell patterns, dense operational controls, workflow states, overlays, form fields, data views, design tokens and theme infrastructure.
|
package/README.ru.md
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
# Orcestr UI
|
|
12
12
|
|
|
13
|
+
## [Demo](https://orcestr.com/ui)
|
|
14
|
+
|
|
15
|
+
Открой live example page, чтобы посмотреть компоненты и паттерны Orcestr UI в контексте.
|
|
16
|
+
|
|
13
17
|
Общая React UI-основа для продуктов Orcestr.
|
|
14
18
|
|
|
15
19
|
Orcestr UI - публичная библиотека компонентов, выделенная из реальной продуктовой разработки Orcestr. Здесь собираются интерфейсные примитивы, которые переиспользуются в product surfaces: application shell, плотные операционные контролы, workflow-состояния, overlays, поля, data views, design tokens и инфраструктура темы.
|
|
@@ -165,25 +165,25 @@ export declare const themePlaygroundPresets: readonly [{
|
|
|
165
165
|
};
|
|
166
166
|
readonly mode: "dark";
|
|
167
167
|
readonly surface: "media";
|
|
168
|
-
readonly accent: "#
|
|
169
|
-
readonly previewBg: "#
|
|
170
|
-
readonly previewPanel: "#
|
|
171
|
-
readonly previewText: "#
|
|
168
|
+
readonly accent: "#f0a6d8";
|
|
169
|
+
readonly previewBg: "#141116";
|
|
170
|
+
readonly previewPanel: "#1d1820";
|
|
171
|
+
readonly previewText: "#f7eef7";
|
|
172
172
|
readonly group: "dark";
|
|
173
173
|
readonly overrides: {
|
|
174
174
|
readonly colors: {
|
|
175
|
-
readonly bg: "#
|
|
176
|
-
readonly panel: "#
|
|
177
|
-
readonly panelSoft: "#
|
|
178
|
-
readonly floating: "#
|
|
179
|
-
readonly brand: "#
|
|
180
|
-
readonly brandStrong: "#
|
|
181
|
-
readonly brandSolid: "#
|
|
182
|
-
readonly brandSolidHover: "#
|
|
183
|
-
readonly brandSoft: "rgb(
|
|
184
|
-
readonly selected: "rgb(
|
|
175
|
+
readonly bg: "#141116";
|
|
176
|
+
readonly panel: "#1d1820";
|
|
177
|
+
readonly panelSoft: "#29212d";
|
|
178
|
+
readonly floating: "#1d1820";
|
|
179
|
+
readonly brand: "#f0a6d8";
|
|
180
|
+
readonly brandStrong: "#ffc1e7";
|
|
181
|
+
readonly brandSolid: "#a84486";
|
|
182
|
+
readonly brandSolidHover: "#bc5399";
|
|
183
|
+
readonly brandSoft: "rgb(240 166 216 / 17%)";
|
|
184
|
+
readonly selected: "rgb(240 166 216 / 16%)";
|
|
185
185
|
readonly warning: "#fbbf24";
|
|
186
|
-
readonly warningSoft: "#
|
|
186
|
+
readonly warningSoft: "#49371c";
|
|
187
187
|
};
|
|
188
188
|
};
|
|
189
189
|
}, {
|
|
@@ -215,23 +215,23 @@ export declare const themePlaygroundPresets: readonly [{
|
|
|
215
215
|
};
|
|
216
216
|
readonly mode: "dark";
|
|
217
217
|
readonly surface: "orcestr";
|
|
218
|
-
readonly accent: "#
|
|
219
|
-
readonly previewBg: "#
|
|
220
|
-
readonly previewPanel: "#
|
|
221
|
-
readonly previewText: "#
|
|
218
|
+
readonly accent: "#7dd3fc";
|
|
219
|
+
readonly previewBg: "#080f1c";
|
|
220
|
+
readonly previewPanel: "#101a2b";
|
|
221
|
+
readonly previewText: "#e9f3ff";
|
|
222
222
|
readonly group: "dark";
|
|
223
223
|
readonly overrides: {
|
|
224
224
|
readonly colors: {
|
|
225
|
-
readonly bg: "#
|
|
226
|
-
readonly panel: "#
|
|
227
|
-
readonly panelSoft: "#
|
|
228
|
-
readonly floating: "#
|
|
229
|
-
readonly brand: "#
|
|
230
|
-
readonly brandStrong: "#
|
|
231
|
-
readonly brandSolid: "#
|
|
232
|
-
readonly brandSolidHover: "#
|
|
233
|
-
readonly brandSoft: "rgb(
|
|
234
|
-
readonly selected: "rgb(
|
|
225
|
+
readonly bg: "#080f1c";
|
|
226
|
+
readonly panel: "#101a2b";
|
|
227
|
+
readonly panelSoft: "#172338";
|
|
228
|
+
readonly floating: "#101a2b";
|
|
229
|
+
readonly brand: "#7dd3fc";
|
|
230
|
+
readonly brandStrong: "#bae6fd";
|
|
231
|
+
readonly brandSolid: "#0369a1";
|
|
232
|
+
readonly brandSolidHover: "#0284c7";
|
|
233
|
+
readonly brandSoft: "rgb(125 211 252 / 16%)";
|
|
234
|
+
readonly selected: "rgb(125 211 252 / 13%)";
|
|
235
235
|
readonly info: "#22d3ee";
|
|
236
236
|
readonly infoSoft: "#083344";
|
|
237
237
|
};
|
|
@@ -158,25 +158,25 @@ export const themePlaygroundPresets = [
|
|
|
158
158
|
},
|
|
159
159
|
mode: 'dark',
|
|
160
160
|
surface: 'media',
|
|
161
|
-
accent: '#
|
|
162
|
-
previewBg: '#
|
|
163
|
-
previewPanel: '#
|
|
164
|
-
previewText: '#
|
|
161
|
+
accent: '#f0a6d8',
|
|
162
|
+
previewBg: '#141116',
|
|
163
|
+
previewPanel: '#1d1820',
|
|
164
|
+
previewText: '#f7eef7',
|
|
165
165
|
group: 'dark',
|
|
166
166
|
overrides: {
|
|
167
167
|
colors: {
|
|
168
|
-
bg: '#
|
|
169
|
-
panel: '#
|
|
170
|
-
panelSoft: '#
|
|
171
|
-
floating: '#
|
|
172
|
-
brand: '#
|
|
173
|
-
brandStrong: '#
|
|
174
|
-
brandSolid: '#
|
|
175
|
-
brandSolidHover: '#
|
|
176
|
-
brandSoft: 'rgb(
|
|
177
|
-
selected: 'rgb(
|
|
168
|
+
bg: '#141116',
|
|
169
|
+
panel: '#1d1820',
|
|
170
|
+
panelSoft: '#29212d',
|
|
171
|
+
floating: '#1d1820',
|
|
172
|
+
brand: '#f0a6d8',
|
|
173
|
+
brandStrong: '#ffc1e7',
|
|
174
|
+
brandSolid: '#a84486',
|
|
175
|
+
brandSolidHover: '#bc5399',
|
|
176
|
+
brandSoft: 'rgb(240 166 216 / 17%)',
|
|
177
|
+
selected: 'rgb(240 166 216 / 16%)',
|
|
178
178
|
warning: '#fbbf24',
|
|
179
|
-
warningSoft: '#
|
|
179
|
+
warningSoft: '#49371c',
|
|
180
180
|
},
|
|
181
181
|
},
|
|
182
182
|
},
|
|
@@ -210,23 +210,23 @@ export const themePlaygroundPresets = [
|
|
|
210
210
|
},
|
|
211
211
|
mode: 'dark',
|
|
212
212
|
surface: 'orcestr',
|
|
213
|
-
accent: '#
|
|
214
|
-
previewBg: '#
|
|
215
|
-
previewPanel: '#
|
|
216
|
-
previewText: '#
|
|
213
|
+
accent: '#7dd3fc',
|
|
214
|
+
previewBg: '#080f1c',
|
|
215
|
+
previewPanel: '#101a2b',
|
|
216
|
+
previewText: '#e9f3ff',
|
|
217
217
|
group: 'dark',
|
|
218
218
|
overrides: {
|
|
219
219
|
colors: {
|
|
220
|
-
bg: '#
|
|
221
|
-
panel: '#
|
|
222
|
-
panelSoft: '#
|
|
223
|
-
floating: '#
|
|
224
|
-
brand: '#
|
|
225
|
-
brandStrong: '#
|
|
226
|
-
brandSolid: '#
|
|
227
|
-
brandSolidHover: '#
|
|
228
|
-
brandSoft: 'rgb(
|
|
229
|
-
selected: 'rgb(
|
|
220
|
+
bg: '#080f1c',
|
|
221
|
+
panel: '#101a2b',
|
|
222
|
+
panelSoft: '#172338',
|
|
223
|
+
floating: '#101a2b',
|
|
224
|
+
brand: '#7dd3fc',
|
|
225
|
+
brandStrong: '#bae6fd',
|
|
226
|
+
brandSolid: '#0369a1',
|
|
227
|
+
brandSolidHover: '#0284c7',
|
|
228
|
+
brandSoft: 'rgb(125 211 252 / 16%)',
|
|
229
|
+
selected: 'rgb(125 211 252 / 13%)',
|
|
230
230
|
info: '#22d3ee',
|
|
231
231
|
infoSoft: '#083344',
|
|
232
232
|
},
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { type OrcestrUiLocale } from '..';
|
|
2
|
+
export type UiExamplePageProps = {
|
|
3
|
+
locale?: OrcestrUiLocale;
|
|
4
|
+
defaultLocale?: OrcestrUiLocale;
|
|
5
|
+
onLocaleChange?: (locale: OrcestrUiLocale) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare function UiExamplePage({ locale: controlledLocale, defaultLocale, onLocaleChange, }?: UiExamplePageProps): import("react/jsx-runtime").JSX.Element;
|
|
2
8
|
//# sourceMappingURL=UiExamplePage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiExamplePage.d.ts","sourceRoot":"","sources":["../../src/example/UiExamplePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UiExamplePage.d.ts","sourceRoot":"","sources":["../../src/example/UiExamplePage.tsx"],"names":[],"mappings":"AAWA,OAAO,EAYH,KAAK,eAAe,EACvB,MAAM,IAAI,CAAC;AA4lBZ,MAAM,MAAM,kBAAkB,GAAG;IAC7B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAC1B,MAAM,EAAE,gBAAgB,EACxB,aAAoB,EACpB,cAAc,GACjB,GAAE,kBAAuB,2CA8CzB"}
|
|
@@ -18,23 +18,34 @@ import {} from './codeSamples';
|
|
|
18
18
|
import { navGroups, navItems } from './exampleData';
|
|
19
19
|
const ORCESTR_LOGO_SRC = '/assets/orcestr/logo.png';
|
|
20
20
|
const UI_EXAMPLE_SCROLL_LEAD = 50;
|
|
21
|
-
|
|
21
|
+
const UI_EXAMPLE_ACTIVE_PROBE_OFFSET = UI_EXAMPLE_SCROLL_LEAD + 220;
|
|
22
|
+
const UI_EXAMPLE_CLICK_TARGET_TOP_TOLERANCE = 180;
|
|
23
|
+
const UI_EXAMPLE_SCROLL_LOCK_TIMEOUT_MS = 1600;
|
|
24
|
+
function scrollUiExampleSection(id, behavior = 'auto') {
|
|
22
25
|
const node = document.getElementById(id);
|
|
23
26
|
const scrollRoot = document.querySelector('.oui-app-shell-content-scroll .oui-scroll-area-viewport');
|
|
24
27
|
if (!node || !scrollRoot) {
|
|
25
|
-
node?.scrollIntoView({ block: 'start', behavior
|
|
28
|
+
node?.scrollIntoView({ block: 'start', behavior });
|
|
26
29
|
return;
|
|
27
30
|
}
|
|
28
31
|
scrollRoot.scrollTo({
|
|
29
32
|
top: uiExampleSectionScrollTop(node, scrollRoot),
|
|
30
|
-
behavior
|
|
33
|
+
behavior,
|
|
31
34
|
});
|
|
32
35
|
}
|
|
33
36
|
function uiExampleSectionScrollTop(node, scrollRoot) {
|
|
34
37
|
const maxTop = scrollRoot
|
|
35
38
|
? Math.max(0, scrollRoot.scrollHeight - scrollRoot.clientHeight)
|
|
36
39
|
: Number.POSITIVE_INFINITY;
|
|
37
|
-
|
|
40
|
+
const targetTop = scrollRoot
|
|
41
|
+
? uiExampleSectionAbsoluteTop(node, scrollRoot)
|
|
42
|
+
: node.offsetTop;
|
|
43
|
+
return Math.min(maxTop, Math.max(0, targetTop - UI_EXAMPLE_SCROLL_LEAD));
|
|
44
|
+
}
|
|
45
|
+
function uiExampleSectionAbsoluteTop(node, scrollRoot) {
|
|
46
|
+
const nodeTop = node.getBoundingClientRect().top;
|
|
47
|
+
const scrollRootTop = scrollRoot.getBoundingClientRect().top;
|
|
48
|
+
return scrollRoot.scrollTop + nodeTop - scrollRootTop;
|
|
38
49
|
}
|
|
39
50
|
function UiExampleContent({ activePresetId, onThemePresetChange, onThemeOverridesChange, locale, onLocaleChange, }) {
|
|
40
51
|
const { theme } = useOrcestrTheme();
|
|
@@ -70,20 +81,14 @@ function UiExampleContent({ activePresetId, onThemePresetChange, onThemeOverride
|
|
|
70
81
|
document.documentElement.classList.add('oui-ui-document-lock');
|
|
71
82
|
document.body.classList.add('oui-ui-document-lock');
|
|
72
83
|
const hash = window.location.hash.replace('#', '');
|
|
73
|
-
let hashSettleTimer = null;
|
|
74
84
|
const hashFrame = hash
|
|
75
85
|
? window.requestAnimationFrame(() => {
|
|
76
86
|
scrollUiExampleSection(hash);
|
|
77
|
-
hashSettleTimer = window.setTimeout(() => {
|
|
78
|
-
scrollUiExampleSection(hash);
|
|
79
|
-
}, 450);
|
|
80
87
|
})
|
|
81
88
|
: null;
|
|
82
89
|
return () => {
|
|
83
90
|
if (hashFrame !== null)
|
|
84
91
|
window.cancelAnimationFrame(hashFrame);
|
|
85
|
-
if (hashSettleTimer !== null)
|
|
86
|
-
window.clearTimeout(hashSettleTimer);
|
|
87
92
|
document.documentElement.classList.remove('oui-ui-document-lock');
|
|
88
93
|
document.body.classList.remove('oui-ui-document-lock');
|
|
89
94
|
};
|
|
@@ -209,7 +214,7 @@ function UiExampleSidebar({ onNavigate }) {
|
|
|
209
214
|
scrollNavigationReleaseTimerRef.current = window.setTimeout(() => {
|
|
210
215
|
if (scrollNavigationTargetRef.current === id)
|
|
211
216
|
scrollNavigationTargetRef.current = null;
|
|
212
|
-
},
|
|
217
|
+
}, UI_EXAMPLE_SCROLL_LOCK_TIMEOUT_MS);
|
|
213
218
|
}, []);
|
|
214
219
|
useEffect(() => {
|
|
215
220
|
const hash = window.location.hash.replace('#', '');
|
|
@@ -233,7 +238,8 @@ function UiExampleSidebar({ onNavigate }) {
|
|
|
233
238
|
return;
|
|
234
239
|
}
|
|
235
240
|
const targetTop = uiExampleSectionScrollTop(targetNode, scrollRoot);
|
|
236
|
-
if (Math.abs(scrollRoot.scrollTop - targetTop) <=
|
|
241
|
+
if (Math.abs(scrollRoot.scrollTop - targetTop) <=
|
|
242
|
+
UI_EXAMPLE_CLICK_TARGET_TOP_TOLERANCE) {
|
|
237
243
|
scrollNavigationTargetRef.current = null;
|
|
238
244
|
setActiveSectionValue(lockedTarget);
|
|
239
245
|
}
|
|
@@ -242,10 +248,12 @@ function UiExampleSidebar({ onNavigate }) {
|
|
|
242
248
|
const bottomDistance = scrollRoot.scrollHeight
|
|
243
249
|
- scrollRoot.clientHeight
|
|
244
250
|
- scrollRoot.scrollTop;
|
|
245
|
-
const top = scrollRoot.scrollTop +
|
|
251
|
+
const top = scrollRoot.scrollTop + UI_EXAMPLE_ACTIVE_PROBE_OFFSET;
|
|
246
252
|
const next = bottomDistance <= 2
|
|
247
253
|
? nodes.at(-1)?.id
|
|
248
|
-
: nodes
|
|
254
|
+
: nodes
|
|
255
|
+
.filter((node) => uiExampleSectionAbsoluteTop(node, scrollRoot) <= top)
|
|
256
|
+
.at(-1)?.id ?? nodes[0]?.id;
|
|
249
257
|
if (next && next !== activeSectionRef.current)
|
|
250
258
|
setActiveSectionValue(next);
|
|
251
259
|
};
|
|
@@ -298,18 +306,26 @@ function UiExampleBrand({ compact = false }) {
|
|
|
298
306
|
function UiExampleHeaderActions({ compact = false, locale, onLocaleChange, }) {
|
|
299
307
|
return (_jsxs("div", { className: 'oui-ui-topbar-actions', "data-compact": compact ? 'true' : undefined, children: [_jsxs("span", { className: 'oui-ui-language-switch', "aria-label": 'UI example language', children: [_jsx("span", { className: 'oui-ui-language-label', children: locale === 'ru' ? 'Язык' : 'Language' }), ['ru', 'en'].map((item) => (_jsx("button", { type: 'button', className: 'oui-ui-language-option', "data-active": locale === item ? 'true' : undefined, "aria-pressed": locale === item, onClick: () => onLocaleChange(item), children: item.toUpperCase() }, item)))] }), _jsxs("a", { className: 'oui-ui-topbar-link', href: 'https://github.com/Artasov/orcestr', target: '_blank', rel: 'noreferrer', children: [_jsx(LuExternalLink, { size: 14, "aria-hidden": true }), _jsx("span", { children: "GitHub" })] })] }));
|
|
300
308
|
}
|
|
301
|
-
export function UiExamplePage() {
|
|
309
|
+
export function UiExamplePage({ locale: controlledLocale, defaultLocale = 'ru', onLocaleChange, } = {}) {
|
|
302
310
|
const firstPreset = getThemePlaygroundPreset('orcestr-dark');
|
|
303
311
|
const [activePresetId, setActivePresetId] = useState(firstPreset.id);
|
|
304
312
|
const [mode, setMode] = useState(firstPreset.mode);
|
|
305
313
|
const [surface, setSurface] = useState(firstPreset.surface);
|
|
306
|
-
const [
|
|
314
|
+
const [internalLocale, setInternalLocale] = useState(defaultLocale);
|
|
307
315
|
const [themeOverrides, setThemeOverrides] = useState(firstPreset.overrides ?? {});
|
|
316
|
+
const locale = controlledLocale ?? internalLocale;
|
|
308
317
|
const handleThemePresetChange = useCallback((preset) => {
|
|
309
318
|
setActivePresetId(preset.id);
|
|
310
319
|
setMode(preset.mode);
|
|
311
320
|
setSurface(preset.surface);
|
|
312
321
|
setThemeOverrides(preset.overrides ?? {});
|
|
313
322
|
}, []);
|
|
314
|
-
|
|
323
|
+
const handleLocaleChange = useCallback((nextLocale) => {
|
|
324
|
+
if (onLocaleChange) {
|
|
325
|
+
onLocaleChange(nextLocale);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
setInternalLocale(nextLocale);
|
|
329
|
+
}, [onLocaleChange]);
|
|
330
|
+
return (_jsx(OrcestrUiProvider, { mode: mode, surface: surface, onModeChange: setMode, onSurfaceChange: setSurface, themeOverrides: themeOverrides, locale: locale, children: _jsx(UiExampleContent, { activePresetId: activePresetId, onThemePresetChange: handleThemePresetChange, onThemeOverridesChange: setThemeOverrides, locale: locale, onLocaleChange: handleLocaleChange }) }));
|
|
315
331
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orcestr/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Shared React UI package for Orcestr products.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"release:minor": "node scripts/release.mjs minor",
|
|
52
52
|
"release:major": "node scripts/release.mjs major",
|
|
53
53
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
54
|
-
"test": "node
|
|
54
|
+
"test": "node scripts/run-tests.mjs"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@tanstack/react-query": "^5.99.0",
|