flet-box 1.0.1 → 1.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/bin/ota/loader.js +6 -1
- package/bin/utils/templates.js +9 -4
- package/package.json +12 -8
- package/src/create-index.sh +2 -2
- package/src/index.d.ts +2 -1
- package/src/index.js +1 -0
- package/src/navigations/AppBar.js +9 -2
- package/src/navigations/Router.js +125 -6
- package/src/navigations/Scaffold.js +5 -2
- package/src/navigations/index.js +2 -0
- package/bin/package.json +0 -45
package/bin/ota/loader.js
CHANGED
|
@@ -331,7 +331,12 @@ async function checkAndUpdate(shippedConfig, activeHash) {
|
|
|
331
331
|
(async function main() {
|
|
332
332
|
let shippedConfig = null;
|
|
333
333
|
try {
|
|
334
|
-
|
|
334
|
+
// Anchored to this script, not the document: on a static host with SPA
|
|
335
|
+
// fallback (GitHub Pages) the app can boot from a deep URL, where a
|
|
336
|
+
// document-relative "./config.json" would resolve to the wrong folder.
|
|
337
|
+
shippedConfig = await fetchJson(
|
|
338
|
+
new URL("./config.json", import.meta.url).href,
|
|
339
|
+
);
|
|
335
340
|
} catch (e) {
|
|
336
341
|
warn("no shipped config.json:", e.message);
|
|
337
342
|
}
|
package/bin/utils/templates.js
CHANGED
|
@@ -607,9 +607,13 @@ echo "✅ Bundle listo: \$TARGET/ Prueba: cd \$TARGET && bash run.sh"
|
|
|
607
607
|
|
|
608
608
|
export const serviceWorkerJs = () => `// service-worker.js - PWA offline support
|
|
609
609
|
const CACHE_NAME = 'fletbox-v2';
|
|
610
|
+
// Deployment prefix: a worker's own URL always sits at the app root, so this
|
|
611
|
+
// is '/' at the host root and '/repo-name/' on a GitHub Pages project site.
|
|
612
|
+
// Hard-coded '/' entries would miss every file under a subpath.
|
|
613
|
+
const BASE = new URL('./', self.location).pathname;
|
|
610
614
|
// The shipped (baked-in) shell, precached so the app opens with no connection.
|
|
611
615
|
// loader.js owns a SEPARATE cache ('fletbox-ota') for downloaded bundles.
|
|
612
|
-
const PRECACHE = [
|
|
616
|
+
const PRECACHE = [BASE, BASE + 'index.html', BASE + 'loader.js', BASE + 'config.json', BASE + 'src/app.js'];
|
|
613
617
|
|
|
614
618
|
self.addEventListener('install', event => {
|
|
615
619
|
event.waitUntil(
|
|
@@ -690,7 +694,7 @@ self.addEventListener('fetch', event => {
|
|
|
690
694
|
const cached = await cache.match(req);
|
|
691
695
|
if (cached) return cached;
|
|
692
696
|
if (req.mode === 'navigate') {
|
|
693
|
-
const shell = await cache.match('
|
|
697
|
+
const shell = await cache.match(BASE + 'index.html');
|
|
694
698
|
if (shell) return shell;
|
|
695
699
|
}
|
|
696
700
|
return Response.error();
|
|
@@ -1422,7 +1426,7 @@ enable: get an approved domain at https://www.google.com/adsense, put your
|
|
|
1422
1426
|
publisher ID in the script, and delete the surrounding \`<!--\` / \`-->\` so the
|
|
1423
1427
|
tag goes live. Ads only render on an approved domain, not on localhost. You can
|
|
1424
1428
|
also drop the \`AdSense\` widget into any screen (see
|
|
1425
|
-
|
|
1429
|
+
https://github.com/kuko53348/flet-box/blob/refactory/docs/widget/AdSense.md).
|
|
1426
1430
|
|
|
1427
1431
|
### AdMob (Android / iOS)
|
|
1428
1432
|
|
|
@@ -1457,7 +1461,8 @@ also drop the \`AdSense\` widget into any screen (see
|
|
|
1457
1461
|
|
|
1458
1462
|
4. Uncomment the \`AdMob\` import and the \`AdMob({...})\` widget in
|
|
1459
1463
|
\`src/screens/HomeScreen.js\` (they are marked with ADMOB comments). Full
|
|
1460
|
-
props in
|
|
1464
|
+
props in
|
|
1465
|
+
https://github.com/kuko53348/flet-box/blob/refactory/docs/widget/AdMob.md.
|
|
1461
1466
|
|
|
1462
1467
|
## Over-the-air updates (OTA)
|
|
1463
1468
|
|
package/package.json
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flet-box",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Declarative, zero-dependency UI framework in vanilla JS — ship web, PWA, Android and iOS from one codebase",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"types": "src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
8
15
|
"bin": {
|
|
9
16
|
"flet-box": "bin/cli.js"
|
|
10
17
|
},
|
|
11
18
|
"scripts": {
|
|
12
19
|
"dev": "node bin/cli.js run --hot",
|
|
13
20
|
"build": "node bin/cli.js createBundle",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
21
|
+
"release": "node bin/cli.js release",
|
|
22
|
+
"test": "node scripts/check-widgets.mjs"
|
|
16
23
|
},
|
|
17
24
|
"keywords": [
|
|
18
25
|
"fletbox",
|
|
@@ -48,9 +55,6 @@
|
|
|
48
55
|
"LICENSE"
|
|
49
56
|
],
|
|
50
57
|
"engines": {
|
|
51
|
-
"node": ">=
|
|
52
|
-
},
|
|
53
|
-
"allowScripts": {
|
|
54
|
-
"esbuild@0.28.2": true
|
|
58
|
+
"node": ">=20.9.0"
|
|
55
59
|
}
|
|
56
60
|
}
|
package/src/create-index.sh
CHANGED
|
@@ -60,7 +60,7 @@ export {
|
|
|
60
60
|
Scaffold, AppBar, Drawer, BottomNavigation, Tabs, DrawerItem,
|
|
61
61
|
openDrawer, closeDrawer, toggleDrawer, destroyDrawer,
|
|
62
62
|
initRouter, goTo, goBack, goForward, replace,
|
|
63
|
-
getCurrentPath, getCurrentRoute, getCurrentRouteConfig,
|
|
63
|
+
getCurrentPath, getBasePath, getCurrentRoute, getCurrentRouteConfig,
|
|
64
64
|
getRoute, isActive, subscribe, useParams, useQueryParams,
|
|
65
65
|
buildUrl, clearRouter
|
|
66
66
|
} from './src/navigations/index.js';
|
|
@@ -178,7 +178,7 @@ export { Drawer, openDrawer, closeDrawer, toggleDrawer, destroyDrawer } from './
|
|
|
178
178
|
export { BottomNavigation } from './BottomNavigation.js';
|
|
179
179
|
export { Tabs } from './Tabs.js';
|
|
180
180
|
export { DrawerItem } from './DrawerItem.js';
|
|
181
|
-
export { initRouter, goTo, goBack, goForward, replace, getCurrentPath, getCurrentRoute, getCurrentRouteConfig, getRoute, isActive, subscribe, useParams, useQueryParams, buildUrl, clearRouter } from './Router.js';
|
|
181
|
+
export { initRouter, goTo, goBack, goForward, replace, getCurrentPath, getBasePath, getCurrentRoute, getCurrentRouteConfig, getRoute, isActive, subscribe, useParams, useQueryParams, buildUrl, clearRouter } from './Router.js';
|
|
182
182
|
EOF
|
|
183
183
|
echo "✅ Created: src/navigations/index.js"
|
|
184
184
|
|
package/src/index.d.ts
CHANGED
|
@@ -977,12 +977,13 @@ declare module 'flet-box' {
|
|
|
977
977
|
// =========================================================================
|
|
978
978
|
// Router
|
|
979
979
|
// =========================================================================
|
|
980
|
-
export function initRouter(routes: Record<string, any>, initialPath?: string): void;
|
|
980
|
+
export function initRouter(routes: Record<string, any>, initialPath?: string, options?: { base?: string }): void;
|
|
981
981
|
export function goTo(path: string, params?: Record<string, any>): void;
|
|
982
982
|
export function goBack(): void;
|
|
983
983
|
export function goForward(): void;
|
|
984
984
|
export function replace(path: string, params?: Record<string, any>): void;
|
|
985
985
|
export function getCurrentPath(): string;
|
|
986
|
+
export function getBasePath(): string;
|
|
986
987
|
export function getCurrentRoute(): any;
|
|
987
988
|
export function getCurrentRouteConfig(): { route: any; params: Record<string, any>; query: Record<string, any>; path: string };
|
|
988
989
|
export function getRoute(path: string): any;
|
package/src/index.js
CHANGED
|
@@ -165,6 +165,8 @@ export const AppBar = (props) => {
|
|
|
165
165
|
display: "flex",
|
|
166
166
|
alignItems: "center",
|
|
167
167
|
justifyContent: "space-between",
|
|
168
|
+
width: "100%",
|
|
169
|
+
boxSizing: "border-box",
|
|
168
170
|
minHeight: 56,
|
|
169
171
|
borderRadius: finalBorderRadius,
|
|
170
172
|
marginTop: finalMarginTop,
|
|
@@ -217,7 +219,10 @@ export const AppBar = (props) => {
|
|
|
217
219
|
}
|
|
218
220
|
|
|
219
221
|
const centerSection = Container({
|
|
220
|
-
flex:
|
|
222
|
+
// Always flex:1 so the title absorbs whatever the leading and action zones
|
|
223
|
+
// do not use. With flex:"none" a long title keeps its intrinsic width and
|
|
224
|
+
// pushes the actions past the viewport edge on narrow screens.
|
|
225
|
+
flex: 1,
|
|
221
226
|
display: "flex",
|
|
222
227
|
alignItems: "center",
|
|
223
228
|
justifyContent: centerTitle ? "center" : "flex-start",
|
|
@@ -232,9 +237,11 @@ export const AppBar = (props) => {
|
|
|
232
237
|
// ========== RIGHT SECTION (only rendered when there are valid actions) ==========
|
|
233
238
|
if (validActions.length > 0) {
|
|
234
239
|
const rightSection = Row({
|
|
240
|
+
// Row defaults to width:"100%", which inside the flex header demands the
|
|
241
|
+
// whole bar width and overflows it. The zone must be content-sized.
|
|
242
|
+
width: "auto",
|
|
235
243
|
alignItems: "center",
|
|
236
244
|
justifyContent: "flex-end",
|
|
237
|
-
paddingRight: paddingRight,
|
|
238
245
|
gap: actionsGap,
|
|
239
246
|
minWidth: 48,
|
|
240
247
|
flexShrink: 0,
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - Dynamic segments: `/user/:id`, `/post/:slug/comments`
|
|
8
8
|
* - Wildcard / 404 routes: `*` or `/404`
|
|
9
9
|
* - Query string parameters
|
|
10
|
+
* - Deployment base paths (`/repo-name/`) for static hosts like GitHub Pages
|
|
10
11
|
* - Browser history integration (pushState / popstate)
|
|
11
12
|
* - Observer pattern (subscribe/notify) so layout shells like Scaffold can
|
|
12
13
|
* re-render when the route changes.
|
|
@@ -42,6 +43,15 @@ let currentQuery = {};
|
|
|
42
43
|
/** @type {Function|null} Removes the popstate event listener; set during initRouter. */
|
|
43
44
|
let removePopStateListener = null;
|
|
44
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Deployment base path the app is served under, e.g. "/flet-box-docs".
|
|
48
|
+
* Empty string means the app owns the host root. Router state stays
|
|
49
|
+
* app-relative; the base is only added when writing browser URLs.
|
|
50
|
+
*
|
|
51
|
+
* @type {string}
|
|
52
|
+
*/
|
|
53
|
+
let basePath = "";
|
|
54
|
+
|
|
45
55
|
// ========== UTILITIES ==========
|
|
46
56
|
|
|
47
57
|
/**
|
|
@@ -132,6 +142,93 @@ const findMatchingRoute = (path) => {
|
|
|
132
142
|
return null;
|
|
133
143
|
};
|
|
134
144
|
|
|
145
|
+
// ========== DEPLOYMENT BASE PATH ==========
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Normalize a deployment base to "" or "/segment(s)" with no trailing slash.
|
|
149
|
+
*
|
|
150
|
+
* @param {string|null|undefined} base - e.g. "/", "flet-box-docs", "/flet-box-docs/".
|
|
151
|
+
* @returns {string} "" for a root-hosted app, otherwise a leading-slash prefix.
|
|
152
|
+
*/
|
|
153
|
+
const normalizeBase = (base) => {
|
|
154
|
+
if (!base) return "";
|
|
155
|
+
let out = String(base).trim();
|
|
156
|
+
if (!out.startsWith("/")) out = `/${out}`;
|
|
157
|
+
out = out.replace(/\/+$/, "");
|
|
158
|
+
return out === "/" ? "" : out;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Build a browser URL from an app-relative path by prefixing the base.
|
|
163
|
+
*
|
|
164
|
+
* @param {string} path - App-relative path, possibly with a query string.
|
|
165
|
+
* @returns {string} Path as seen by the browser.
|
|
166
|
+
*/
|
|
167
|
+
const withBase = (path) => `${basePath}${path}`;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Remove the deployment base from a browser URL path.
|
|
171
|
+
*
|
|
172
|
+
* @param {string} path - Path as seen by the browser.
|
|
173
|
+
* @returns {string} App-relative path.
|
|
174
|
+
*/
|
|
175
|
+
const stripBase = (path) =>
|
|
176
|
+
basePath && path.startsWith(basePath)
|
|
177
|
+
? path.slice(basePath.length) || "/"
|
|
178
|
+
: path;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Work out which prefix of a browser path is the deployment base.
|
|
182
|
+
*
|
|
183
|
+
* Static hosts such as GitHub Pages serve a project site under
|
|
184
|
+
* `/<repo>/`, so `location.pathname` is `/<repo>/<route>` while the app's
|
|
185
|
+
* route map only knows `/<route>`. Scanning prefixes from the shortest one
|
|
186
|
+
* and returning the first whose remainder matches a registered route keeps
|
|
187
|
+
* root-hosted apps untouched (`base` resolves to "").
|
|
188
|
+
*
|
|
189
|
+
* @param {string} rawPath - Browser path, including any base prefix.
|
|
190
|
+
* @returns {string} Normalized base, or "" when no prefix yields a match.
|
|
191
|
+
*/
|
|
192
|
+
const detectBase = (rawPath) => {
|
|
193
|
+
const clean = cleanPath(rawPath);
|
|
194
|
+
if (findMatchingRoute(clean)) return "";
|
|
195
|
+
|
|
196
|
+
const segments = clean.split("/").filter(Boolean);
|
|
197
|
+
// i === segments.length covers the bare subpath root ("/repo/"), where the
|
|
198
|
+
// remainder is the app's own "/" route.
|
|
199
|
+
for (let i = 1; i <= segments.length; i++) {
|
|
200
|
+
const candidate = `/${segments.slice(0, i).join("/")}`;
|
|
201
|
+
const rest = segments.slice(i);
|
|
202
|
+
const remainder = rest.length ? `/${rest.join("/")}` : "/";
|
|
203
|
+
if (findMatchingRoute(remainder)) return normalizeBase(candidate);
|
|
204
|
+
}
|
|
205
|
+
return "";
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Resolve the deployment base for the current document.
|
|
210
|
+
*
|
|
211
|
+
* Precedence: explicit `base` option > `window.__FLETBOX_BASE__` (only when
|
|
212
|
+
* the live URL actually sits under it, so the same bundle works when
|
|
213
|
+
* packaged by Capacitor at the origin root) > auto-detection from the URL.
|
|
214
|
+
*
|
|
215
|
+
* @param {string|null|undefined} explicitBase - Base passed to initRouter.
|
|
216
|
+
* @param {string} rawPath - Browser path the app is being entered on.
|
|
217
|
+
* @returns {string} Normalized base.
|
|
218
|
+
*/
|
|
219
|
+
const resolveBase = (explicitBase, rawPath) => {
|
|
220
|
+
const explicit = normalizeBase(explicitBase);
|
|
221
|
+
if (explicit) return explicit;
|
|
222
|
+
|
|
223
|
+
if (typeof window !== "undefined") {
|
|
224
|
+
const declared = normalizeBase(window.__FLETBOX_BASE__);
|
|
225
|
+
if (declared && (rawPath === `${declared}/` || rawPath.startsWith(`${declared}/`))) {
|
|
226
|
+
return declared;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return detectBase(rawPath);
|
|
230
|
+
};
|
|
231
|
+
|
|
135
232
|
// ========== INITIALIZATION ==========
|
|
136
233
|
|
|
137
234
|
/**
|
|
@@ -146,8 +243,9 @@ const findMatchingRoute = (path) => {
|
|
|
146
243
|
*
|
|
147
244
|
* @param {Object.<string, *>} routesConfig - Map of path patterns to components/config.
|
|
148
245
|
* @param {string|null} [initialPath=null] - Override the starting path; defaults to window.location.pathname.
|
|
246
|
+
* @param {{base?: string}} [options={}] - `base` pins the deployment prefix; auto-detected when omitted.
|
|
149
247
|
*/
|
|
150
|
-
export const initRouter = (routesConfig, initialPath = null) => {
|
|
248
|
+
export const initRouter = (routesConfig, initialPath = null, options = {}) => {
|
|
151
249
|
routes = routesConfig;
|
|
152
250
|
|
|
153
251
|
// Prefer the explicit initialPath; fall back to the live browser URL so
|
|
@@ -157,6 +255,11 @@ export const initRouter = (routesConfig, initialPath = null) => {
|
|
|
157
255
|
urlPath = window.location.pathname;
|
|
158
256
|
}
|
|
159
257
|
|
|
258
|
+
// Peel the deployment prefix off the browser URL before matching so a site
|
|
259
|
+
// served under /repo-name/ resolves to its routes instead of redirecting.
|
|
260
|
+
basePath = resolveBase(options.base, urlPath || "/");
|
|
261
|
+
if (urlPath) urlPath = stripBase(urlPath);
|
|
262
|
+
|
|
160
263
|
// Last resort: use the first registered route or the root.
|
|
161
264
|
if (!urlPath) {
|
|
162
265
|
urlPath = Object.keys(routes)[0] || "/";
|
|
@@ -188,9 +291,13 @@ export const initRouter = (routesConfig, initialPath = null) => {
|
|
|
188
291
|
// redirected to the first route above).
|
|
189
292
|
if (
|
|
190
293
|
typeof window !== "undefined" &&
|
|
191
|
-
window.location.pathname !== currentPath
|
|
294
|
+
window.location.pathname !== withBase(currentPath)
|
|
192
295
|
) {
|
|
193
|
-
window.history.replaceState(
|
|
296
|
+
window.history.replaceState(
|
|
297
|
+
{ path: currentPath },
|
|
298
|
+
"",
|
|
299
|
+
withBase(currentPath),
|
|
300
|
+
);
|
|
194
301
|
}
|
|
195
302
|
|
|
196
303
|
// Listen for browser-native back/forward navigation so the router state
|
|
@@ -198,7 +305,8 @@ export const initRouter = (routesConfig, initialPath = null) => {
|
|
|
198
305
|
if (typeof window !== "undefined") {
|
|
199
306
|
if (removePopStateListener) removePopStateListener();
|
|
200
307
|
const handlePopState = (event) => {
|
|
201
|
-
const path =
|
|
308
|
+
const path =
|
|
309
|
+
event.state?.path || stripBase(window.location.pathname);
|
|
202
310
|
if (path !== currentPath) {
|
|
203
311
|
currentPath = path;
|
|
204
312
|
const match = findMatchingRoute(currentPath);
|
|
@@ -243,7 +351,7 @@ export const goTo = (path, params = {}) => {
|
|
|
243
351
|
currentQuery = { ...queryParams, ...params };
|
|
244
352
|
|
|
245
353
|
if (typeof window !== "undefined") {
|
|
246
|
-
window.history.pushState({ path: currentPath }, "", path);
|
|
354
|
+
window.history.pushState({ path: currentPath }, "", withBase(path));
|
|
247
355
|
}
|
|
248
356
|
notify();
|
|
249
357
|
} else {
|
|
@@ -278,7 +386,7 @@ export const replace = (path, params = {}) => {
|
|
|
278
386
|
currentQuery = { ...queryParams, ...params };
|
|
279
387
|
|
|
280
388
|
if (typeof window !== "undefined") {
|
|
281
|
-
window.history.replaceState({ path: currentPath }, "", path);
|
|
389
|
+
window.history.replaceState({ path: currentPath }, "", withBase(path));
|
|
282
390
|
}
|
|
283
391
|
notify();
|
|
284
392
|
}
|
|
@@ -316,6 +424,15 @@ export const goForward = () => {
|
|
|
316
424
|
*/
|
|
317
425
|
export const getCurrentPath = () => currentPath;
|
|
318
426
|
|
|
427
|
+
/**
|
|
428
|
+
* Returns the deployment base the router resolved at init, e.g. "/flet-box-docs".
|
|
429
|
+
* Empty string for a root-hosted app. Use it to build asset or document URLs
|
|
430
|
+
* that must survive being served from a subpath.
|
|
431
|
+
*
|
|
432
|
+
* @returns {string}
|
|
433
|
+
*/
|
|
434
|
+
export const getBasePath = () => basePath;
|
|
435
|
+
|
|
319
436
|
/**
|
|
320
437
|
* Returns a shallow copy of the current dynamic route params.
|
|
321
438
|
* Mutations to the returned object do not affect the router state.
|
|
@@ -454,6 +571,7 @@ export const clearRouter = () => {
|
|
|
454
571
|
listeners = [];
|
|
455
572
|
currentParams = {};
|
|
456
573
|
currentQuery = {};
|
|
574
|
+
basePath = "";
|
|
457
575
|
};
|
|
458
576
|
|
|
459
577
|
export default {
|
|
@@ -463,6 +581,7 @@ export default {
|
|
|
463
581
|
goBack,
|
|
464
582
|
goForward,
|
|
465
583
|
getCurrentPath,
|
|
584
|
+
getBasePath,
|
|
466
585
|
getCurrentRoute,
|
|
467
586
|
getCurrentRouteConfig,
|
|
468
587
|
getRoute,
|
|
@@ -18,6 +18,7 @@ import { initRouter, getCurrentRoute, subscribe } from "./Router.js";
|
|
|
18
18
|
* @property {number} [navSideBarWidth=260] - Legacy alias for leftNavBarWidth (deprecated).
|
|
19
19
|
* @property {"left"|"right"} [navSideBarPosition="left"] - Legacy: which side navSideBar renders on.
|
|
20
20
|
* @property {Object} [routes] - Route map object for router mode (path → component).
|
|
21
|
+
* @property {string} [basePath] - Deployment prefix, e.g. "/flet-box-docs". Auto-detected when omitted.
|
|
21
22
|
* @property {string} [backgroundColor] - Background color of the scaffold shell.
|
|
22
23
|
* @property {boolean} [closeDrawerOnNavigate=false] - Whether to close the drawer automatically on route change.
|
|
23
24
|
*/
|
|
@@ -54,6 +55,7 @@ export const Scaffold = (props) => {
|
|
|
54
55
|
navSideBarWidth = 260,
|
|
55
56
|
navSideBarPosition = "left",
|
|
56
57
|
routes,
|
|
58
|
+
basePath,
|
|
57
59
|
backgroundColor = colors.background,
|
|
58
60
|
closeDrawerOnNavigate = false,
|
|
59
61
|
...rest
|
|
@@ -81,11 +83,12 @@ export const Scaffold = (props) => {
|
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
// Bootstrap the router with the current browser URL so deep-links work
|
|
84
|
-
// on first load without redirecting to "/".
|
|
86
|
+
// on first load without redirecting to "/". `basePath` pins the deployment
|
|
87
|
+
// prefix when the app is served from a subpath (e.g. GitHub Pages).
|
|
85
88
|
if (isRouterMode && routesConfig) {
|
|
86
89
|
const currentUrl =
|
|
87
90
|
typeof window !== "undefined" ? window.location.pathname : "/";
|
|
88
|
-
initRouter(routesConfig, currentUrl);
|
|
91
|
+
initRouter(routesConfig, currentUrl, { base: basePath });
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
// Resolve the legacy navSideBar prop to the appropriate side.
|
package/src/navigations/index.js
CHANGED
|
@@ -36,6 +36,8 @@ export {
|
|
|
36
36
|
replace,
|
|
37
37
|
/** Returns the currently active path. */
|
|
38
38
|
getCurrentPath,
|
|
39
|
+
/** Returns the deployment base path, e.g. "/flet-box-docs". */
|
|
40
|
+
getBasePath,
|
|
39
41
|
/** Returns the component/config for the current route. */
|
|
40
42
|
getCurrentRoute,
|
|
41
43
|
/** Returns the full route state (route, params, query, path). */
|
package/bin/package.json
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "flet-box",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "Ultra-lightweight UI framework for vanilla JS web apps",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "src/index.js",
|
|
7
|
-
"types": "src/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"flet-box": "./bin/cli.js"
|
|
10
|
-
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"dev": "node bin/cli.js run --hot",
|
|
13
|
-
"build": "node bin/cli.js createBundle",
|
|
14
|
-
"test": "echo \"No tests yet\"",
|
|
15
|
-
"prepublishOnly": "npm run build"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"fletbox",
|
|
19
|
-
"flet-box",
|
|
20
|
-
"framework",
|
|
21
|
-
"ui",
|
|
22
|
-
"flutter-like",
|
|
23
|
-
"vanilla-js",
|
|
24
|
-
"lightweight",
|
|
25
|
-
"pwa",
|
|
26
|
-
"no-dependencies",
|
|
27
|
-
"zero-deps"
|
|
28
|
-
],
|
|
29
|
-
"author": "Flet-Box Team",
|
|
30
|
-
"license": "MIT",
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"chokidar": "^4.0.3",
|
|
33
|
-
"esbuild": "^0.28.0",
|
|
34
|
-
"ws": "^8.21.0"
|
|
35
|
-
},
|
|
36
|
-
"files": [
|
|
37
|
-
"bin/",
|
|
38
|
-
"src/",
|
|
39
|
-
"README.md",
|
|
40
|
-
"LICENSE"
|
|
41
|
-
],
|
|
42
|
-
"engines": {
|
|
43
|
-
"node": ">=18.0.0"
|
|
44
|
-
}
|
|
45
|
-
}
|