@public-ui/sample-react 1.7.0-rc.6 → 1.7.0-rc.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/package.json +9 -12
- package/prettier.config.js +0 -1
- package/src/App.tsx +36 -163
- package/src/components/Sidebar.tsx +81 -0
- package/src/components/split-button/routes.ts +1 -1
- package/src/shares/store.ts +1 -1
- package/src/style.scss +8 -59
- package/unocss.config.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@public-ui/sample-react",
|
|
3
|
-
"version": "1.7.0-rc.
|
|
3
|
+
"version": "1.7.0-rc.7",
|
|
4
4
|
"description": "This app contains samples for the KoliBri/Public UI",
|
|
5
5
|
"license": "EUPL-1.2",
|
|
6
6
|
"scripts": {
|
|
@@ -20,16 +20,16 @@
|
|
|
20
20
|
"kolibri-sample-react-test-build": "test-build.sh"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@leanup/stack": "1.3.
|
|
24
|
-
"@leanup/stack-react": "1.3.
|
|
25
|
-
"@leanup/stack-webpack": "1.3.
|
|
23
|
+
"@leanup/stack": "1.3.48",
|
|
24
|
+
"@leanup/stack-react": "1.3.48",
|
|
25
|
+
"@leanup/stack-webpack": "1.3.48",
|
|
26
26
|
"@public-oss/kolibri-themes": "0.0.3",
|
|
27
|
-
"@public-ui/components": "1.7.0-rc.
|
|
28
|
-
"@public-ui/react": "1.7.0-rc.
|
|
29
|
-
"@public-ui/themes": "1.7.0-rc.
|
|
27
|
+
"@public-ui/components": "1.7.0-rc.7",
|
|
28
|
+
"@public-ui/react": "1.7.0-rc.7",
|
|
29
|
+
"@public-ui/themes": "1.7.0-rc.7",
|
|
30
30
|
"@types/react": "18.2.21",
|
|
31
31
|
"@types/react-dom": "18.2.7",
|
|
32
|
-
"@unocss/preset-
|
|
32
|
+
"@unocss/preset-uno": "0.55.7",
|
|
33
33
|
"@unocss/webpack": "0.55.7",
|
|
34
34
|
"ajv": "8.12.0",
|
|
35
35
|
"chromedriver": "116.0.0",
|
|
@@ -59,8 +59,5 @@
|
|
|
59
59
|
"tsconfig.json",
|
|
60
60
|
"unocss.config.ts",
|
|
61
61
|
"webpack.config.js"
|
|
62
|
-
]
|
|
63
|
-
"publishConfig": {
|
|
64
|
-
"registry": "https://registry.npmjs.org/"
|
|
65
|
-
}
|
|
62
|
+
]
|
|
66
63
|
}
|
package/prettier.config.js
CHANGED
package/src/App.tsx
CHANGED
|
@@ -1,29 +1,18 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { Navigate, Route, Routes } from 'react-router-dom';
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import { Navigate, Route, Routes, useSearchParams } from 'react-router-dom';
|
|
3
3
|
import { Route as MyRoute, Routes as MyRoutes } from './shares/types';
|
|
4
4
|
|
|
5
5
|
import { Option } from '@public-ui/components';
|
|
6
|
-
import { KolAlert
|
|
7
|
-
import { FC, useState } from 'react';
|
|
6
|
+
import { KolAlert } from '@public-ui/react';
|
|
8
7
|
import { ROUTES } from './shares/routes';
|
|
9
|
-
import {
|
|
8
|
+
import { Theme, THEME_OPTIONS } from './shares/theme';
|
|
10
9
|
import PackageJson from '../package.json';
|
|
11
|
-
import { getTheme,
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import { getTheme, getThemeName, setStorage, setTheme } from './shares/store';
|
|
11
|
+
import { Sidebar } from './components/Sidebar';
|
|
12
|
+
import { useLocation } from 'react-router';
|
|
14
13
|
|
|
15
14
|
setStorage(localStorage);
|
|
16
15
|
|
|
17
|
-
const getThemeFromLocation = () => {
|
|
18
|
-
if (THEME_REGEX.test(window.location.hash)) {
|
|
19
|
-
const match = window.location.hash.match(THEME_REGEX);
|
|
20
|
-
if (Array.isArray(match) && match.length > 0) {
|
|
21
|
-
return match[0].replace(THEME_REGEX, '$1').toLowerCase();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return getTheme();
|
|
25
|
-
};
|
|
26
|
-
|
|
27
16
|
const getRouteList = (routes: MyRoutes, offset = '/'): string[] => {
|
|
28
17
|
let list: string[] = [];
|
|
29
18
|
for (const key in routes) {
|
|
@@ -88,168 +77,52 @@ const getRouteTree = (routes: MyRoutes): ReturnType<typeof Route>[] => {
|
|
|
88
77
|
};
|
|
89
78
|
|
|
90
79
|
const ROUTE_LIST = getRouteList(ROUTES);
|
|
80
|
+
const ROUTE_TREE = getRouteTree(ROUTES);
|
|
91
81
|
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
const getIndexOfRoute = (str: string) => {
|
|
95
|
-
return ROUTE_LIST.indexOf(clearHash(str));
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
type CustomRoute = { label: string; value: string };
|
|
99
|
-
const componentList: CustomRoute[] = [];
|
|
82
|
+
const componentList: Map<string, Option<string>> = new Map();
|
|
100
83
|
ROUTE_LIST.forEach((route) => {
|
|
101
84
|
const routeSplit = route.split('/');
|
|
102
|
-
if (
|
|
85
|
+
if (!componentList.has(routeSplit[1])) {
|
|
86
|
+
componentList.set(routeSplit[1], {
|
|
87
|
+
label: routeSplit[1],
|
|
88
|
+
value: route,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
103
91
|
});
|
|
104
92
|
|
|
105
|
-
function getComponentFromSample(url: string): string {
|
|
106
|
-
const routeSplit = url.split('/');
|
|
107
|
-
routeSplit[2] = 'basic';
|
|
108
|
-
return routeSplit.join('/');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
93
|
export const App: FC = () => {
|
|
112
|
-
const
|
|
113
|
-
const [
|
|
114
|
-
const
|
|
115
|
-
const
|
|
94
|
+
const routerLocation = useLocation();
|
|
95
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
96
|
+
const theme = searchParams.get('theme') ?? getTheme();
|
|
97
|
+
const hideMenus = searchParams.has('hideMenus');
|
|
116
98
|
|
|
117
|
-
|
|
118
|
-
return getComponentFromSample(sample);
|
|
119
|
-
}, [sample]);
|
|
99
|
+
setTheme(theme as Theme); // set for `getTheme` usages within the application
|
|
120
100
|
|
|
121
101
|
document.title = `KoliBri-Handout - ${getThemeName(getTheme())} | v${PackageJson.version}`;
|
|
122
102
|
document.body.setAttribute('class', theme);
|
|
123
103
|
document.body.dataset.theme = theme;
|
|
124
104
|
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}, 500);
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const componentSelectOn = {
|
|
132
|
-
onChange: (_e: Event, v: unknown) => {
|
|
133
|
-
/**
|
|
134
|
-
* Drop first event as a temporary bugfix for the following issue:
|
|
135
|
-
* When navigated to a component example which is not "basic" it would navigate away from it on the first event, because the select only stores the basic routes.
|
|
136
|
-
* e.g. accordion/header would become accordion/basic.
|
|
137
|
-
* This problem will become obsolete when the select gets replaced with a proper navigation (https://github.com/public-ui/kolibri/issues/5064)
|
|
138
|
-
*/
|
|
139
|
-
if (firstComponentChangeEvent) {
|
|
140
|
-
setFirstComponentChangeEvent(false);
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const path = (v as string[])[0];
|
|
145
|
-
setSample(path);
|
|
146
|
-
window.location.href = `#${path}?theme=${theme}`;
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const on = {
|
|
151
|
-
onChange: (_event: Event, value: unknown) => {
|
|
152
|
-
if (active) {
|
|
153
|
-
value = Array.isArray(value) ? value[0] : value;
|
|
154
|
-
setTheme(value as Theme);
|
|
155
|
-
window.location.href =
|
|
156
|
-
window.location.href
|
|
157
|
-
.replace(THEME_REGEX, '')
|
|
158
|
-
.replace(/(\?|&{1,})$/g, '')
|
|
159
|
-
.replace(/&{2,}/g, '&') + `?theme=${value as string}`;
|
|
160
|
-
window.location.reload();
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
const next = {
|
|
166
|
-
onClick: () => {
|
|
167
|
-
let idx = getIndexOfRoute(window.location.hash);
|
|
168
|
-
if (idx >= ROUTE_LIST.length - 1) {
|
|
169
|
-
idx = 0;
|
|
170
|
-
} else {
|
|
171
|
-
idx += 1;
|
|
172
|
-
}
|
|
173
|
-
setSample(clearHash(ROUTE_LIST[idx]));
|
|
174
|
-
window.location.href = `#${ROUTE_LIST[idx]}?theme=${theme}`;
|
|
175
|
-
},
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
const prev = {
|
|
179
|
-
onClick: () => {
|
|
180
|
-
let idx = getIndexOfRoute(window.location.hash);
|
|
181
|
-
if (idx <= 0) {
|
|
182
|
-
idx = ROUTE_LIST.length - 1;
|
|
183
|
-
} else {
|
|
184
|
-
idx -= 1;
|
|
185
|
-
}
|
|
186
|
-
setSample(clearHash(ROUTE_LIST[idx]));
|
|
187
|
-
window.location.href = `#${ROUTE_LIST[idx]}?theme=${theme}`;
|
|
188
|
-
},
|
|
105
|
+
const handleThemeChange = (theme: unknown) => {
|
|
106
|
+
setSearchParams({ theme: theme as string });
|
|
107
|
+
window.location.reload();
|
|
189
108
|
};
|
|
190
109
|
|
|
191
110
|
return (
|
|
192
|
-
<div className=
|
|
193
|
-
|
|
194
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
<KolVersion _version={PackageJson.version}></KolVersion>
|
|
205
|
-
</dd>
|
|
206
|
-
</dl>
|
|
207
|
-
{active && (
|
|
208
|
-
<>
|
|
209
|
-
<KolButton
|
|
210
|
-
_ariaLabel="Weiter zum nächsten Komponenten-Beispiel"
|
|
211
|
-
_icon="codicon codicon-arrow-right"
|
|
212
|
-
_hideLabel
|
|
213
|
-
_label="Weiter"
|
|
214
|
-
_on={next}
|
|
215
|
-
_tooltipAlign="left"
|
|
216
|
-
/>
|
|
217
|
-
<KolButton
|
|
218
|
-
_ariaLabel="Weiter zum nächsten Komponenten-Beispiel"
|
|
219
|
-
_icon="codicon codicon-arrow-left"
|
|
220
|
-
_hideLabel
|
|
221
|
-
_label="Zurück"
|
|
222
|
-
_on={prev}
|
|
223
|
-
_tooltipAlign="right"
|
|
224
|
-
_variant="ghost"
|
|
225
|
-
/>
|
|
226
|
-
</>
|
|
227
|
-
)}
|
|
228
|
-
<KolSelect
|
|
229
|
-
className="col-span-2 sm:col-auto"
|
|
230
|
-
_disabled={!active}
|
|
231
|
-
_hideLabel
|
|
232
|
-
_label="Komponente wechseln"
|
|
233
|
-
_id="theme-toggle"
|
|
234
|
-
_list={componentList}
|
|
235
|
-
_on={componentSelectOn}
|
|
236
|
-
_value={[currentComponent]}
|
|
237
|
-
></KolSelect>
|
|
238
|
-
<KolSelect
|
|
239
|
-
_label="Theme wechseln"
|
|
240
|
-
className="col-span-2 sm:col-auto"
|
|
241
|
-
_hideLabel
|
|
242
|
-
_disabled={!active}
|
|
243
|
-
_id="theme-toggle"
|
|
244
|
-
_list={THEME_OPTIONS}
|
|
245
|
-
_on={on}
|
|
246
|
-
_value={[theme]}
|
|
247
|
-
></KolSelect>
|
|
248
|
-
</div>
|
|
249
|
-
<hr aria-hidden="true" />
|
|
111
|
+
<div className={!hideMenus ? 'app-container' : ''} data-theme={theme}>
|
|
112
|
+
{!hideMenus && (
|
|
113
|
+
<Sidebar
|
|
114
|
+
version={PackageJson.version}
|
|
115
|
+
theme={theme}
|
|
116
|
+
sample={routerLocation.pathname}
|
|
117
|
+
routes={ROUTES}
|
|
118
|
+
routeList={ROUTE_LIST}
|
|
119
|
+
onThemeChange={handleThemeChange}
|
|
120
|
+
/>
|
|
121
|
+
)}
|
|
122
|
+
|
|
250
123
|
<div className="p-4">
|
|
251
124
|
<Routes>
|
|
252
|
-
{
|
|
125
|
+
{ROUTE_TREE}
|
|
253
126
|
<Route path="*" element={<KolAlert _type="info">This code example has not been migrated yet - it's coming soon!</KolAlert>} />
|
|
254
127
|
</Routes>
|
|
255
128
|
</div>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React, { FC, useState } from 'react';
|
|
2
|
+
import { KolButton, KolHeading, KolLink, KolSelect, KolVersion } from '@public-ui/react';
|
|
3
|
+
import { THEME_OPTIONS } from '../shares/theme';
|
|
4
|
+
import { Routes } from '../shares/types';
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
version: string;
|
|
8
|
+
theme: string;
|
|
9
|
+
routes: Routes;
|
|
10
|
+
routeList: string[];
|
|
11
|
+
sample: string;
|
|
12
|
+
onThemeChange: (theme: unknown) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const Sidebar: FC<Props> = ({ version, theme, routes, routeList, sample, onThemeChange }) => {
|
|
16
|
+
/* KolSelect calls onChange initially by design - work around this with a state variable */
|
|
17
|
+
const [isFirstThemeSelectChange, setIsFirstThemeSelectChange] = useState(true);
|
|
18
|
+
|
|
19
|
+
const getIndexOfSample = () => routeList.indexOf(sample);
|
|
20
|
+
const formatSampleAsLabel = () => sample.replace(/\//g, ' ');
|
|
21
|
+
|
|
22
|
+
const handleThemeSelectChange = (_event: Event, value: unknown) => {
|
|
23
|
+
if (isFirstThemeSelectChange) {
|
|
24
|
+
setIsFirstThemeSelectChange(false);
|
|
25
|
+
} else {
|
|
26
|
+
onThemeChange((value as [string])[0]);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const handleLinkClick = (event: Event) => {
|
|
31
|
+
location.replace((event.target as HTMLLinkElement).href); // KoliBri prevents the default click behavior as soon as an event listener is set, so we need to reimplement it.
|
|
32
|
+
document.documentElement.scrollIntoView({ behavior: 'smooth' });
|
|
33
|
+
// @todo set focus?
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handlePreviousClick = () => {
|
|
37
|
+
const currentIndex = getIndexOfSample();
|
|
38
|
+
const nextIndex = currentIndex === 0 ? routeList.length - 1 : currentIndex - 1;
|
|
39
|
+
location.replace(`#${routeList[nextIndex]}`);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handleNextClick = () => {
|
|
43
|
+
const currentIndex = getIndexOfSample();
|
|
44
|
+
const nextIndex = currentIndex === routeList.length - 1 ? 0 : currentIndex + 1;
|
|
45
|
+
location.replace(`#${routeList[nextIndex]}`);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<aside className="app-sidebar p-4">
|
|
50
|
+
<div className="flex flex-justify-between flex-items-center">
|
|
51
|
+
<KolHeading _label="KoliBri React"></KolHeading>
|
|
52
|
+
<KolVersion _version={version}></KolVersion>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<KolSelect _label="Theme wählen" _list={THEME_OPTIONS} _on={{ onChange: handleThemeSelectChange }} _value={[theme]} class="mt"></KolSelect>
|
|
56
|
+
|
|
57
|
+
<KolHeading _label="Komponenten" _level={2} className="block mt"></KolHeading>
|
|
58
|
+
<div className="flex flex-justify-between flex-items-center mt">
|
|
59
|
+
<KolButton _icon="codicon codicon-arrow-left" _hideLabel _label="Vorherige Komponente auswählen" _on={{ onClick: handlePreviousClick }} />
|
|
60
|
+
{formatSampleAsLabel()} ({getIndexOfSample() + 1}/{routeList.length})
|
|
61
|
+
<KolButton _icon="codicon codicon-arrow-right" _hideLabel _label="Nächste Komponente auswählen" _on={{ onClick: handleNextClick }} />
|
|
62
|
+
</div>
|
|
63
|
+
<nav className="block mt">
|
|
64
|
+
<ul className="m0 p0 list-inside">
|
|
65
|
+
{Object.entries(routes).map(([parentName, children]) => (
|
|
66
|
+
<li key={parentName} className="mt-2">
|
|
67
|
+
{parentName}
|
|
68
|
+
<ul className="list-inside ml p0">
|
|
69
|
+
{Object.keys(children).map((childName) => (
|
|
70
|
+
<li key={`${parentName}/${childName}`}>
|
|
71
|
+
<KolLink _label={childName} _href={`#/${parentName}/${childName}`} _on={{ onClick: handleLinkClick }} />
|
|
72
|
+
</li>
|
|
73
|
+
))}
|
|
74
|
+
</ul>
|
|
75
|
+
</li>
|
|
76
|
+
))}
|
|
77
|
+
</ul>
|
|
78
|
+
</nav>
|
|
79
|
+
</aside>
|
|
80
|
+
);
|
|
81
|
+
};
|
package/src/shares/store.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isTheme, Store, Theme } from './theme';
|
|
2
|
-
import PackageJson from '
|
|
2
|
+
import PackageJson from '@public-ui/components/package.json';
|
|
3
3
|
import { THEME_OPTIONS } from './theme';
|
|
4
4
|
import { Option } from '@public-ui/components';
|
|
5
5
|
|
package/src/style.scss
CHANGED
|
@@ -19,71 +19,20 @@ hr {
|
|
|
19
19
|
grid-template-columns: auto auto;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
.
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
.app-container {
|
|
23
|
+
display: grid;
|
|
24
|
+
grid-template-columns: 360px auto;
|
|
25
|
+
height: 100%;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
.toolbar dl {
|
|
32
|
-
order: 2;
|
|
33
|
-
display: flex;
|
|
34
|
-
gap: 0.5em;
|
|
35
|
-
justify-self: start;
|
|
36
|
-
place-items: center;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.toolbar dd {
|
|
40
|
-
margin: 0;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.toolbar kol-select {
|
|
44
|
-
order: 3;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.toolbar kol-button[_label="Weiter"] {
|
|
48
|
-
order: 4;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@media only screen and (max-width: 1024px) {
|
|
52
|
-
.toolbar {
|
|
53
|
-
display: grid;
|
|
54
|
-
gap: 1rem;
|
|
55
|
-
grid-template-columns: 1fr 1fr;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.toolbar kol-button[_label="Zurück"] {
|
|
59
|
-
order: 3;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.toolbar dl {
|
|
63
|
-
order: 1;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.toolbar kol-select {
|
|
67
|
-
order: 2;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.toolbar kol-button[_label="Weiter"] {
|
|
71
|
-
order: 4;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@media only screen and (max-width: 512px) {
|
|
76
|
-
|
|
77
|
-
.toolbar dl,
|
|
78
|
-
.toolbar kol-select {
|
|
79
|
-
grid-column: span 2;
|
|
80
|
-
}
|
|
28
|
+
.app-sidebar {
|
|
29
|
+
border-right: 1px solid gray;
|
|
30
|
+
font-family: sans-serif;
|
|
81
31
|
}
|
|
82
32
|
|
|
83
33
|
@media print {
|
|
84
|
-
|
|
85
34
|
.no-print,
|
|
86
35
|
.no-print * {
|
|
87
36
|
display: none !important;
|
|
88
37
|
}
|
|
89
|
-
}
|
|
38
|
+
}
|
package/unocss.config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineConfig } from '@unocss/webpack';
|
|
2
|
-
import {
|
|
2
|
+
import { presetUno } from '@unocss/preset-uno';
|
|
3
3
|
|
|
4
4
|
// ts-prune-ignore-next
|
|
5
5
|
export default defineConfig({
|
|
6
|
-
presets: [
|
|
6
|
+
presets: [presetUno()],
|
|
7
7
|
});
|