@protobase/ui 0.40.7 → 0.40.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/app.js +7 -2
- package/dist/app/new-version/messages.js +6 -2
- package/dist/app/new-version/new-version-banner.js +37 -0
- package/dist/app/pages/blocks/record-cards.js +14 -4
- package/dist/app/related-cards/related-cards.js +18 -13
- package/dist/app-shell/app-shell.js +6 -3
- package/dist/app-shell/sidebar-notice.js +12 -0
- package/dist/app-shell/sidebar.d.ts +1 -1
- package/dist/app-shell/sidebar.js +2 -1
- package/dist/package.js +1 -1
- package/dist/primitives/snap-row-width.js +13 -0
- package/dist/primitives/snap-row.js +21 -0
- package/dist/shell/assets/app-DXbtlR1O.js +9 -0
- package/dist/shell/assets/{index-BX850JXd.css → index-DT92y8N1.css} +1 -1
- package/dist/shell/assets/{index-B37wY6Go.js → index-hbOjGIrj.js} +2 -2
- package/dist/shell/assets/{records-map-DD0ZBUZe.js → records-map-DW4-2p9A.js} +2 -2
- package/dist/shell/assets/{shared-protobase-ui-pUw1X1dc.js → shared-protobase-ui-DOLAGMZi.js} +2 -2
- package/dist/shell/index.html +4 -4
- package/dist/shell/protobase.shell.json +1 -1
- package/dist/shell/protobase.sw.js +2 -2
- package/dist/shell-source-maps/assets/app-DXbtlR1O.js.map +1 -0
- package/dist/shell-source-maps/assets/{index-B37wY6Go.js.map → index-hbOjGIrj.js.map} +1 -1
- package/dist/shell-source-maps/assets/{records-map-DD0ZBUZe.js.map → records-map-DW4-2p9A.js.map} +1 -1
- package/dist/shell-source-maps/assets/{shared-protobase-ui-pUw1X1dc.js.map → shared-protobase-ui-DOLAGMZi.js.map} +1 -1
- package/package.json +4 -4
- package/dist/shell/assets/app-BpvlppLd.js +0 -9
- package/dist/shell-source-maps/assets/app-BpvlppLd.js.map +0 -1
package/dist/app/app.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { setFallbackLocale } from "../locale/active-locale.js";
|
|
2
2
|
import { accountMenuItems } from "../account/account-pages.js";
|
|
3
|
+
import { useSidebarNoticeShown } from "../app-shell/sidebar-notice.js";
|
|
3
4
|
import { AppShell } from "../app-shell/app-shell.js";
|
|
4
5
|
import { AuthProvider, useAuth } from "../auth/auth-provider.js";
|
|
5
6
|
import { AccountSecurityPage } from "../account/account-security-page.js";
|
|
@@ -52,6 +53,7 @@ import { PluginNotice } from "../plugins/plugin-notice.js";
|
|
|
52
53
|
import { RecordPage } from "./record-page.js";
|
|
53
54
|
import { SourceNotice } from "./source-notice.js";
|
|
54
55
|
import { useGlobalSearch } from "./search/use-global-search.js";
|
|
56
|
+
import { NewVersionBanner } from "./new-version/new-version-banner.js";
|
|
55
57
|
import { NewVersionButton } from "./new-version/new-version-button.js";
|
|
56
58
|
import { NewVersionToast } from "./new-version/new-version-toast.js";
|
|
57
59
|
import { RuntimeUpdateButton } from "./runtime/runtime-update.js";
|
|
@@ -142,7 +144,8 @@ const Routes = ({ workspace, sidebarMode, assistant, runtime }) => {
|
|
|
142
144
|
url: runtimeUrl,
|
|
143
145
|
client: runtime
|
|
144
146
|
});
|
|
145
|
-
const
|
|
147
|
+
const sidebarBanner = useSidebarNoticeShown(sidebarMode ?? "text-small");
|
|
148
|
+
const reloadButton = meta.versionChange && !sidebarBanner && /* @__PURE__ */ jsx(NewVersionButton, {});
|
|
146
149
|
const role = useActiveRole(useCallback(() => reopenIn(basePath), [basePath]), Boolean(user));
|
|
147
150
|
const acting = user && actingUser(user, role.current);
|
|
148
151
|
const admin = acting ? isAdmin(acting) : false;
|
|
@@ -244,6 +247,7 @@ const Routes = ({ workspace, sidebarMode, assistant, runtime }) => {
|
|
|
244
247
|
onSwitch: role.switchTo
|
|
245
248
|
} : void 0,
|
|
246
249
|
onNavigate: open,
|
|
250
|
+
sidebarNotice: /* @__PURE__ */ jsx(NewVersionBanner, {}),
|
|
247
251
|
search: search.available ? {
|
|
248
252
|
placeholder: search.placeholder,
|
|
249
253
|
text: search.text,
|
|
@@ -289,13 +293,14 @@ const Routes = ({ workspace, sidebarMode, assistant, runtime }) => {
|
|
|
289
293
|
};
|
|
290
294
|
const Authenticated = ({ baseUrl, client, sources, workspace, sidebarMode, ui, assistant, runtime }) => {
|
|
291
295
|
const { state, session, markSignedOut } = useAuth();
|
|
296
|
+
const sidebarBanner = useSidebarNoticeShown(sidebarMode ?? "text-small");
|
|
292
297
|
return /* @__PURE__ */ jsx(ApiProvider, {
|
|
293
298
|
baseUrl,
|
|
294
299
|
client,
|
|
295
300
|
sources,
|
|
296
301
|
token: state.kind === "visitor" ? void 0 : session.token,
|
|
297
302
|
onUnauthenticated: markSignedOut,
|
|
298
|
-
children: /* @__PURE__ */ jsx(MetaGate, { children: /* @__PURE__ */ jsxs(ToastProvider, { children: [/* @__PURE__ */ jsx(NewVersionToast, {}), /* @__PURE__ */ jsx(PluginGate, {
|
|
303
|
+
children: /* @__PURE__ */ jsx(MetaGate, { children: /* @__PURE__ */ jsxs(ToastProvider, { children: [!sidebarBanner && /* @__PURE__ */ jsx(NewVersionToast, {}), /* @__PURE__ */ jsx(PluginGate, {
|
|
299
304
|
ui,
|
|
300
305
|
children: /* @__PURE__ */ jsx(Routes, {
|
|
301
306
|
workspace,
|
|
@@ -6,14 +6,18 @@ const text = defineMessages({
|
|
|
6
6
|
description: "Reload the page to use the new version, when it suits you.",
|
|
7
7
|
reload: "Reload",
|
|
8
8
|
reloadPage: "Reload page",
|
|
9
|
-
reloadPageHint: "Reload page to use the new version"
|
|
9
|
+
reloadPageHint: "Reload page to use the new version",
|
|
10
|
+
bannerTitle: "{} updated",
|
|
11
|
+
bannerLine: "Save your work, then click here to reload. You may see errors until you do."
|
|
10
12
|
},
|
|
11
13
|
nl: {
|
|
12
14
|
title: "Deze app is bijgewerkt",
|
|
13
15
|
description: "Laad de pagina opnieuw voor de nieuwe versie, wanneer het uitkomt.",
|
|
14
16
|
reload: "Opnieuw laden",
|
|
15
17
|
reloadPage: "Opnieuw laden",
|
|
16
|
-
reloadPageHint: "Opnieuw laden om de nieuwe versie te gebruiken"
|
|
18
|
+
reloadPageHint: "Opnieuw laden om de nieuwe versie te gebruiken",
|
|
19
|
+
bannerTitle: "{} bijgewerkt",
|
|
20
|
+
bannerLine: "Sla je werk op en klik hier om te herladen. Tot dan kunnen er fouten optreden."
|
|
17
21
|
}
|
|
18
22
|
});
|
|
19
23
|
//#endregion
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useRouter } from "../router.js";
|
|
2
|
+
import { useAdminMeta } from "../meta-gate.js";
|
|
3
|
+
import { slotted } from "../../locale/slotted.js";
|
|
4
|
+
import { text } from "./messages.js";
|
|
5
|
+
import { RotateCw } from "lucide-react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/app/new-version/new-version-banner.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Across the bottom of a full-width sidebar, from the moment the page keeps its `/meta` for a new version until it
|
|
10
|
+
* reloads: the app's name, that it was updated, and a click that reloads, asking first while a guard holds unsaved
|
|
11
|
+
* changes. It stands in for `NewVersionToast` and `NewVersionButton`, which float over the page.
|
|
12
|
+
*/
|
|
13
|
+
const NewVersionBanner = () => {
|
|
14
|
+
const { versionChange, appName } = useAdminMeta();
|
|
15
|
+
const { reload } = useRouter();
|
|
16
|
+
if (!versionChange) return null;
|
|
17
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
18
|
+
type: "button",
|
|
19
|
+
onClick: reload,
|
|
20
|
+
className: "flex w-full shrink-0 items-start gap-2 border-t border-warning/40 bg-warning-soft px-3.5 py-2 text-left text-warning-text transition-colors hover:bg-warning/15 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary",
|
|
21
|
+
children: [/* @__PURE__ */ jsx(RotateCw, {
|
|
22
|
+
"aria-hidden": true,
|
|
23
|
+
className: "mt-0.5 size-3.5 shrink-0"
|
|
24
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
25
|
+
className: "flex min-w-0 flex-col gap-0.5",
|
|
26
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
27
|
+
className: "break-words font-semibold",
|
|
28
|
+
children: appName ? slotted(text("bannerTitle"), appName) : text("title")
|
|
29
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
30
|
+
className: "text-xs",
|
|
31
|
+
children: text("bannerLine")
|
|
32
|
+
})]
|
|
33
|
+
})]
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
export { NewVersionBanner };
|
|
@@ -4,13 +4,22 @@ import { listColumnNames } from "../../../live/columns-from-model.js";
|
|
|
4
4
|
import { propsOf } from "./block-props.js";
|
|
5
5
|
import { RelatedCards } from "../../related-cards/related-cards.js";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import { cardsLayoutOf } from "@protobase/layout";
|
|
7
8
|
//#region src/app/pages/blocks/record-cards.tsx
|
|
9
|
+
const shares = {
|
|
10
|
+
"1/4": 1 / 4,
|
|
11
|
+
"1/3": 1 / 3,
|
|
12
|
+
"1/2": 1 / 2,
|
|
13
|
+
"2/3": 2 / 3
|
|
14
|
+
};
|
|
8
15
|
/**
|
|
9
|
-
* What a filter finds as the record page's related cards, stacked full width
|
|
10
|
-
* section's, with no card frame around them, so no card sits in another.
|
|
16
|
+
* What a filter finds as the record page's related cards, stacked full width or in a row that scrolls sideways, under
|
|
17
|
+
* a heading like a record page section's, with no card frame around them, so no card sits in another.
|
|
11
18
|
*/
|
|
12
19
|
const RecordCardsBlock = ({ node, slots }) => {
|
|
13
|
-
const
|
|
20
|
+
const props = propsOf(node);
|
|
21
|
+
const { resource, filter = "", sort = "", fields, cardActions = [], limit = 10, display, title, description, empty } = props;
|
|
22
|
+
const { layout, cardWidth } = cardsLayoutOf(props);
|
|
14
23
|
const { resources, views } = useAdminMeta();
|
|
15
24
|
const model = resources[resource];
|
|
16
25
|
if (!model) return null;
|
|
@@ -31,7 +40,8 @@ const RecordCardsBlock = ({ node, slots }) => {
|
|
|
31
40
|
actions: cardActions,
|
|
32
41
|
limit,
|
|
33
42
|
display,
|
|
34
|
-
empty
|
|
43
|
+
empty,
|
|
44
|
+
carousel: layout === "carousel" ? shares[cardWidth] : void 0
|
|
35
45
|
})
|
|
36
46
|
})
|
|
37
47
|
});
|
|
@@ -5,6 +5,7 @@ import { defaultOrderBy } from "../list-order.js";
|
|
|
5
5
|
import { AppLink } from "../use-app-address.js";
|
|
6
6
|
import { ErrorBanner } from "../error-banner.js";
|
|
7
7
|
import { scopeOf, useCount, useListPage } from "../pages/use-layout-data.js";
|
|
8
|
+
import { SnapRow } from "../../primitives/snap-row.js";
|
|
8
9
|
import { text } from "../embedded-list/messages.js";
|
|
9
10
|
import { cutOffNote } from "../embedded-list/cut-off-note.js";
|
|
10
11
|
import { embeddedDisplay, viewAllAddress } from "../embedded-list/embedded-display.js";
|
|
@@ -14,10 +15,10 @@ import { ArrowRight } from "lucide-react";
|
|
|
14
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
16
|
//#region src/app/related-cards/related-cards.tsx
|
|
16
17
|
/**
|
|
17
|
-
* The first `limit` records of a list as cards stacked full width
|
|
18
|
-
* link to the whole list beside a note such as "The first 10 of 37." when there are more.
|
|
18
|
+
* The first `limit` records of a list as cards stacked full width or in a `carousel`, each with its fields and its
|
|
19
|
+
* actions' buttons, and a link to the whole list beside a note such as "The first 10 of 37." when there are more.
|
|
19
20
|
*/
|
|
20
|
-
const RelatedCards = ({ model, view, filter, sort, fields, actions, limit, display, empty }) => {
|
|
21
|
+
const RelatedCards = ({ model, view, filter, sort, fields, actions, limit, display, empty, carousel }) => {
|
|
21
22
|
const xs = useIsXs();
|
|
22
23
|
const orderBy = sort || defaultOrderBy(model, view);
|
|
23
24
|
const page = useListPage(model, {
|
|
@@ -39,20 +40,24 @@ const RelatedCards = ({ model, view, filter, sort, fields, actions, limit, displ
|
|
|
39
40
|
className: "text-muted-foreground",
|
|
40
41
|
children: empty ?? text$1("nothingYet")
|
|
41
42
|
});
|
|
43
|
+
const cards = rows.map((row) => {
|
|
44
|
+
const scope = scopeOf(model, row);
|
|
45
|
+
return /* @__PURE__ */ jsx(RelatedCard, {
|
|
46
|
+
scope,
|
|
47
|
+
view,
|
|
48
|
+
fields,
|
|
49
|
+
actions
|
|
50
|
+
}, scope.key);
|
|
51
|
+
});
|
|
42
52
|
const note = count.data === void 0 ? void 0 : cutOffNote(rows.length, count.data, false);
|
|
43
53
|
return /* @__PURE__ */ jsxs("div", {
|
|
44
54
|
className: "flex flex-col gap-3",
|
|
45
|
-
children: [/* @__PURE__ */ jsx("ul", {
|
|
55
|
+
children: [carousel === void 0 ? /* @__PURE__ */ jsx("ul", {
|
|
46
56
|
className: "flex flex-col gap-3",
|
|
47
|
-
children:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
view,
|
|
52
|
-
fields,
|
|
53
|
-
actions
|
|
54
|
-
}, scope.key);
|
|
55
|
-
})
|
|
57
|
+
children: cards
|
|
58
|
+
}) : /* @__PURE__ */ jsx(SnapRow, {
|
|
59
|
+
share: carousel,
|
|
60
|
+
children: cards
|
|
56
61
|
}), /* @__PURE__ */ jsxs("div", {
|
|
57
62
|
className: "flex flex-wrap items-center justify-between gap-2",
|
|
58
63
|
children: [/* @__PURE__ */ jsx("p", {
|
|
@@ -4,14 +4,16 @@ import { BottomBar } from "./bottom-bar.js";
|
|
|
4
4
|
import { Drawer } from "./drawer.js";
|
|
5
5
|
import { PageScrollContext, usePageGutter, usePageInsets } from "./page-scroll.js";
|
|
6
6
|
import { Sidebar } from "./sidebar.js";
|
|
7
|
+
import { useSidebarNoticeShown } from "./sidebar-notice.js";
|
|
7
8
|
import { TopBarSlotContext } from "./top-bar-slot.js";
|
|
8
9
|
import { TopBar } from "./top-bar.js";
|
|
9
10
|
import { useEffect, useRef, useState } from "react";
|
|
10
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
12
|
//#region src/app-shell/app-shell.tsx
|
|
12
13
|
const drawerId = "app-drawer";
|
|
13
|
-
const AppShell = ({ sidebarMode, activeItem, breadcrumb, user, workspace, appName, appIcon, logo, actions, rightPanel, forceExpanded, profileMenuOpen, navGroups, userMenu, bottomBar, onNavigate, onSignOut, signIn, organizations, roles, theme, search, pageScroll: scrollsByDefault = false, className, children }) => {
|
|
14
|
+
const AppShell = ({ sidebarMode, activeItem, breadcrumb, user, workspace, appName, appIcon, logo, actions, rightPanel, sidebarNotice, forceExpanded, profileMenuOpen, navGroups, userMenu, bottomBar, onNavigate, onSignOut, signIn, organizations, roles, theme, search, pageScroll: scrollsByDefault = false, className, children }) => {
|
|
14
15
|
const desktop = useIsDesktop();
|
|
16
|
+
const noticeShown = useSidebarNoticeShown(sidebarMode);
|
|
15
17
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
16
18
|
useEffect(() => {
|
|
17
19
|
if (desktop) setDrawerOpen(false);
|
|
@@ -24,9 +26,10 @@ const AppShell = ({ sidebarMode, activeItem, breadcrumb, user, workspace, appNam
|
|
|
24
26
|
const bottomBarRef = useRef(null);
|
|
25
27
|
usePageInsets(pageScroll, topBarRef, bottomBarRef, Boolean(tabs));
|
|
26
28
|
usePageGutter(pageScroll);
|
|
27
|
-
const sidebar = (mode, sticky = false) => /* @__PURE__ */ jsx(Sidebar, {
|
|
29
|
+
const sidebar = (mode, sticky = false, notice) => /* @__PURE__ */ jsx(Sidebar, {
|
|
28
30
|
mode,
|
|
29
31
|
sticky,
|
|
32
|
+
notice,
|
|
30
33
|
activeItem,
|
|
31
34
|
user,
|
|
32
35
|
workspace,
|
|
@@ -49,7 +52,7 @@ const AppShell = ({ sidebarMode, activeItem, breadcrumb, user, workspace, appNam
|
|
|
49
52
|
children: /* @__PURE__ */ jsxs("div", {
|
|
50
53
|
className: cn(pageScroll ? "flex min-h-full w-full overflow-x-clip bg-background" : "relative flex h-full min-h-0 w-full overflow-hidden bg-background", className),
|
|
51
54
|
children: [
|
|
52
|
-
desktop ? sidebar(sidebarMode, pageScroll) : /* @__PURE__ */ jsx(Drawer, {
|
|
55
|
+
desktop ? sidebar(sidebarMode, pageScroll, noticeShown && sidebarNotice) : /* @__PURE__ */ jsx(Drawer, {
|
|
53
56
|
id: drawerId,
|
|
54
57
|
open: drawerOpen,
|
|
55
58
|
onClose: () => setDrawerOpen(false),
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useIsDesktop } from "../lib/use-media-query.js";
|
|
2
|
+
import { isTextMode } from "./sidebar-mode.js";
|
|
3
|
+
//#region src/app-shell/sidebar-notice.ts
|
|
4
|
+
/**
|
|
5
|
+
* Whether the shell draws its `sidebarNotice`: where the sidebar shows at full width, from the `md` breakpoint up in a
|
|
6
|
+
* text mode. Collapsed to icons, or a drawer on phones, it has no room, so the app says the same another way.
|
|
7
|
+
*/
|
|
8
|
+
const useSidebarNoticeShown = (mode) => {
|
|
9
|
+
return useIsDesktop() && isTextMode(mode);
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { useSidebarNoticeShown };
|
|
@@ -11,7 +11,7 @@ import { SidebarGroup } from "./sidebar-group.js";
|
|
|
11
11
|
import { LogIn } from "lucide-react";
|
|
12
12
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13
13
|
//#region src/app-shell/sidebar.tsx
|
|
14
|
-
const Sidebar = ({ mode, activeItem, user, workspace, appName, appIcon, forceExpanded, profileMenuOpen, groups = navGroups, userMenu, onNavigate, onSignOut, signIn, organizations, roles, theme, sticky, logo: SidebarLogo = Logo }) => {
|
|
14
|
+
const Sidebar = ({ mode, activeItem, user, workspace, appName, appIcon, forceExpanded, profileMenuOpen, groups = navGroups, userMenu, onNavigate, onSignOut, signIn, organizations, roles, theme, sticky, logo: SidebarLogo = Logo, notice }) => {
|
|
15
15
|
const expanding = mode === "icon-expand";
|
|
16
16
|
const expanded = expanding && forceExpanded;
|
|
17
17
|
const inline = isTextMode(mode) || expanding;
|
|
@@ -51,6 +51,7 @@ const Sidebar = ({ mode, activeItem, user, workspace, appName, appIcon, forceExp
|
|
|
51
51
|
}, item.id))]
|
|
52
52
|
}, group.label))
|
|
53
53
|
}),
|
|
54
|
+
notice,
|
|
54
55
|
/* @__PURE__ */ jsx("div", {
|
|
55
56
|
className: cn("shrink-0 border-t p-2", mode !== "text-large" && mode !== "text-small" && !expanding && "flex justify-center"),
|
|
56
57
|
children: user ? /* @__PURE__ */ jsx(ProfileMenu, {
|
package/dist/package.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/primitives/snap-row-width.ts
|
|
2
|
+
/** The space between the items of a `SnapRow`, Tailwind's `gap-3`. */
|
|
3
|
+
const snapRowGap = "0.75rem";
|
|
4
|
+
/**
|
|
5
|
+
* How wide an item of a row is at `share` of the row's width, the gaps taken off so that `1 / share` items fill it
|
|
6
|
+
* exactly: a third leaves room for three items and the two gaps between them.
|
|
7
|
+
*/
|
|
8
|
+
const snapItemWidth = (share) => {
|
|
9
|
+
if (!(share > 0 && share <= 1)) throw new Error(`An item's share of a row is above 0 and at most 1, not ${share}`);
|
|
10
|
+
return `calc((100% + ${snapRowGap}) * ${share} - ${snapRowGap})`;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { snapItemWidth, snapRowGap };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { snapItemWidth, snapRowGap } from "./snap-row-width.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/primitives/snap-row.tsx
|
|
4
|
+
/**
|
|
5
|
+
* A list laid out as one row that scrolls sideways, by touch, trackpad, wheel or its scrollbar, and snaps each item to
|
|
6
|
+
* its left edge. Each item is `share` of the row wide, but never narrower than 12rem or the row, so narrow shares stay
|
|
7
|
+
* readable on a phone; the items are top aligned. The row scrolls on its own because the page cannot scroll sideways,
|
|
8
|
+
* and only sideways: it is as tall as its tallest item. A swipe past its last item stops there.
|
|
9
|
+
*/
|
|
10
|
+
const SnapRow = ({ share, label, children }) => /* @__PURE__ */ jsx("ul", {
|
|
11
|
+
"aria-label": label,
|
|
12
|
+
className: "flex snap-x snap-mandatory items-start overflow-x-auto overflow-y-hidden overscroll-x-contain pb-1 *:w-(--snap-item-width) *:min-w-[min(100%,12rem)] *:shrink-0 *:snap-start",
|
|
13
|
+
style: {
|
|
14
|
+
gap: snapRowGap,
|
|
15
|
+
scrollbarWidth: "thin",
|
|
16
|
+
"--snap-item-width": snapItemWidth(share)
|
|
17
|
+
},
|
|
18
|
+
children
|
|
19
|
+
});
|
|
20
|
+
//#endregion
|
|
21
|
+
export { SnapRow };
|