@plumile/ui 0.1.115 → 0.1.116
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/lib/esm/admin/templates/admin_shell_layout/AdminShellLayout.js +15 -14
- package/lib/esm/admin/templates/admin_shell_layout/AdminShellLayout.js.map +1 -1
- package/lib/esm/atomic/molecules/markdown/components/MarkdownArticleContainer.css.js +0 -1
- package/lib/esm/atomic/molecules/markdown/components/MarkdownTableCell.css.js +1 -0
- package/lib/esm/backoffice/organisms/backoffice_data_table/BackofficeDataTable.js +59 -56
- package/lib/esm/backoffice/organisms/backoffice_data_table/BackofficeDataTable.js.map +1 -1
- package/lib/esm/backoffice/organisms/backoffice_data_table/backofficeDataTable.css.js +2 -2
- package/lib/esm/backoffice/organisms/backoffice_data_table/backofficeDataTable.css.js.map +1 -1
- package/lib/esm/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.js +3 -2
- package/lib/esm/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.js.map +1 -1
- package/lib/esm/backoffice/templates/detail_page_template/DetailPageTemplate.js +42 -39
- package/lib/esm/backoffice/templates/detail_page_template/DetailPageTemplate.js.map +1 -1
- package/lib/esm/backoffice/templates/detail_page_template/detailPageTemplate.css.js +3 -3
- package/lib/esm/backoffice/templates/detail_page_template/detailPageTemplate.css.js.map +1 -1
- package/lib/esm/backoffice/templates/list_page_template/ListPageTemplate.js +45 -29
- package/lib/esm/backoffice/templates/list_page_template/ListPageTemplate.js.map +1 -1
- package/lib/esm/backoffice/templates/list_page_template/listPageTemplate.css.js +73 -13
- package/lib/esm/backoffice/templates/list_page_template/listPageTemplate.css.js.map +1 -1
- package/lib/esm/components/data-table/DataTable.css.js +52 -52
- package/lib/esm/components/data-table/DataTable.css.js.map +1 -1
- package/lib/esm/components/data-table/DataTable.js +43 -39
- package/lib/esm/components/data-table/DataTable.js.map +1 -1
- package/lib/esm/components/data-table/ResponsiveRecordList.css.js +7 -7
- package/lib/esm/components/data-table/ResponsiveRecordList.css.js.map +1 -1
- package/lib/esm/components/data-table/ResponsiveRecordList.js +86 -61
- package/lib/esm/components/data-table/ResponsiveRecordList.js.map +1 -1
- package/lib/esm/components/data-table/VirtualizedConnectionTable.js +158 -142
- package/lib/esm/components/data-table/VirtualizedConnectionTable.js.map +1 -1
- package/lib/esm/components/layout/AppShell.js +2 -1
- package/lib/esm/components/layout/AppShell.js.map +1 -1
- package/lib/esm/components/layout/PageShell.css.js +8 -8
- package/lib/esm/components/layout/PageShell.css.js.map +1 -1
- package/lib/esm/components/layout/PageShell.js +115 -107
- package/lib/esm/components/layout/PageShell.js.map +1 -1
- package/lib/esm/style.css +1 -1
- package/lib/types/admin/templates/admin_shell_layout/AdminShellLayout.d.ts +3 -2
- package/lib/types/admin/templates/admin_shell_layout/AdminShellLayout.d.ts.map +1 -1
- package/lib/types/backoffice/organisms/backoffice_data_table/BackofficeDataTable.d.ts +3 -2
- package/lib/types/backoffice/organisms/backoffice_data_table/BackofficeDataTable.d.ts.map +1 -1
- package/lib/types/backoffice/organisms/backoffice_data_table/backofficeDataTable.css.d.ts +1 -0
- package/lib/types/backoffice/organisms/backoffice_data_table/backofficeDataTable.css.d.ts.map +1 -1
- package/lib/types/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.d.ts +3 -2
- package/lib/types/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.d.ts.map +1 -1
- package/lib/types/backoffice/templates/detail_page_template/DetailPageTemplate.d.ts.map +1 -1
- package/lib/types/backoffice/templates/detail_page_template/detailPageTemplate.css.d.ts +5 -0
- package/lib/types/backoffice/templates/detail_page_template/detailPageTemplate.css.d.ts.map +1 -1
- package/lib/types/backoffice/templates/list_page_template/ListPageTemplate.d.ts +1 -0
- package/lib/types/backoffice/templates/list_page_template/ListPageTemplate.d.ts.map +1 -1
- package/lib/types/backoffice/templates/list_page_template/listPageTemplate.css.d.ts +17 -2
- package/lib/types/backoffice/templates/list_page_template/listPageTemplate.css.d.ts.map +1 -1
- package/lib/types/components/data-table/DataTable.css.d.ts +2 -0
- package/lib/types/components/data-table/DataTable.css.d.ts.map +1 -1
- package/lib/types/components/data-table/DataTable.d.ts +5 -2
- package/lib/types/components/data-table/DataTable.d.ts.map +1 -1
- package/lib/types/components/data-table/ResponsiveRecordList.css.d.ts +2 -0
- package/lib/types/components/data-table/ResponsiveRecordList.css.d.ts.map +1 -1
- package/lib/types/components/data-table/ResponsiveRecordList.d.ts +1 -1
- package/lib/types/components/data-table/ResponsiveRecordList.d.ts.map +1 -1
- package/lib/types/components/data-table/VirtualizedConnectionTable.d.ts +3 -2
- package/lib/types/components/data-table/VirtualizedConnectionTable.d.ts.map +1 -1
- package/lib/types/components/layout/AppShell.d.ts +3 -2
- package/lib/types/components/layout/AppShell.d.ts.map +1 -1
- package/lib/types/components/layout/PageShell.css.d.ts +3 -0
- package/lib/types/components/layout/PageShell.css.d.ts.map +1 -1
- package/lib/types/components/layout/PageShell.d.ts +3 -1
- package/lib/types/components/layout/PageShell.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageShell.css.js","names":[],"sources":["../../../../src/components/layout/PageShell.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { recipe } from '@vanilla-extract/recipes';\n\nimport { sprinkles } from '../../theme/sprinkles.css.js';\nimport { vars } from '../../theme/themeContract.js';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 1023px)';\n\nexport const shell = sprinkles({\n display: 'flex',\n width: 'full',\n backgroundColor: 'background',\n backgroundImage: 'pageShellSurface',\n});\n\nexport const page = sprinkles({\n paddingLeft: 2,\n paddingRight: 2,\n paddingTop: 2,\n paddingBottom: 2,\n height: {\n base: 'screen',\n max1023: 'auto',\n },\n flex: 1,\n minWidth: 0,\n});\n\nexport const pageWithSidePanel = sprinkles({\n display: 'flex',\n alignItems: 'stretch',\n gap: {\n base: 0,\n max1023: 3,\n },\n minWidth: 0,\n flexDirection: {\n base: 'row',\n max1023: 'column',\n },\n height: {\n base: 'full',\n max1023: 'auto',\n },\n});\n\nexport const sidebarColumn = sprinkles({\n position: 'sticky',\n top: 0,\n height: 'screen',\n flexShrink: 0,\n display: 'flex',\n overflow: 'hidden',\n});\n\nexport const sidebarColumnMobile = style({\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n position: 'fixed',\n top: 0,\n left: 0,\n bottom: 0,\n width: '20rem',\n maxWidth: '85vw',\n transform: 'translateX(-100%)',\n transitionProperty: 'transform',\n transitionDuration: vars.transitionDuration[200],\n transitionTimingFunction: vars.transitionTimingFunction.ease,\n zIndex: vars.zIndex[30],\n backgroundColor: vars.colors.surface,\n borderRight: `1px solid ${vars.colors.borderSubtle}`,\n },\n },\n});\n\nexport const sidebarColumnMobileOpen = style({\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n transform: 'translateX(0)',\n },\n },\n});\n\nexport const sidebarInner = style([\n sprinkles({\n display: 'flex',\n height: 'full',\n }),\n {\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n paddingTop: '3.75rem',\n },\n },\n },\n]);\n\nexport const mobileSidebarBackdrop = style({\n display: 'none',\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n display: 'block',\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(15, 23, 42, 0.32)',\n opacity: 0,\n pointerEvents: 'none',\n transitionProperty: 'opacity',\n transitionDuration: vars.transitionDuration[200],\n transitionTimingFunction: vars.transitionTimingFunction.ease,\n zIndex: vars.zIndex[20],\n },\n },\n});\n\nexport const mobileSidebarBackdropOpen = style({\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n opacity: 1,\n pointerEvents: 'auto',\n },\n },\n});\n\nexport const mobileSidebarToggle = sprinkles({\n display: {\n base: 'none',\n max1023: 'inline-flex',\n },\n alignItems: 'center',\n justifyContent: 'center',\n width: 10,\n height: 10,\n borderRadius: 'lg',\n borderStyle: 'solid',\n borderWidth: 'default',\n borderColor: 'border',\n backgroundColor: 'surface',\n color: 'text',\n cursor: 'pointer',\n flexShrink: 0,\n});\n\nexport const desktopSidebarToggle = style([\n sprinkles({\n display: {\n base: 'inline-flex',\n max1023: 'none',\n },\n alignItems: 'center',\n justifyContent: 'center',\n width: 10,\n height: 10,\n borderRadius: 'lg',\n borderStyle: 'solid',\n borderWidth: 'default',\n borderColor: 'border',\n backgroundColor: 'surface',\n color: 'text',\n cursor: 'pointer',\n flexShrink: 0,\n transitionProperty: 'default',\n transitionDuration: 150,\n transitionTimingFunction: 'ease',\n }),\n {\n selectors: {\n '&:hover': {\n borderColor: vars.colors.primaryLight,\n backgroundColor: vars.colors.surfaceMuted,\n color: vars.colors.primary,\n },\n '&:focus-visible': {\n outline: `2px solid ${vars.colors.primary}`,\n outlineOffset: '2px',\n },\n },\n },\n]);\n\nexport const mobileSidebarClose = sprinkles({\n display: {\n base: 'none',\n max1023: 'inline-flex',\n },\n position: {\n base: 'static',\n max1023: 'absolute',\n },\n right: {\n base: 0,\n max1023: 3,\n },\n top: {\n base: 0,\n max1023: 3,\n },\n zIndex: 40,\n alignItems: 'center',\n justifyContent: 'center',\n width: 10,\n height: 10,\n borderRadius: 'lg',\n borderStyle: 'solid',\n borderWidth: 'default',\n borderColor: 'border',\n backgroundColor: 'surface',\n color: 'text',\n cursor: 'pointer',\n});\n\nexport const mainColumn = sprinkles({\n flex: 1,\n height: 'full',\n minWidth: 0,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: 'surface',\n overflow: 'hidden',\n borderRadius: 'lg',\n borderWidth: 'default',\n borderStyle: 'solid',\n borderColor: 'borderSubtle',\n boxShadow: 'inkSoft',\n});\n\nexport const mainColumnWithSidePanel = sprinkles({\n height: {\n base: 'full',\n max1023: 'auto',\n },\n});\n\nexport const sidePanel = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n minHeight: 0,\n height: {\n base: 'full',\n max1023: 'auto',\n },\n});\n\nexport const sidePanelSurface = sprinkles({\n flex: 'none',\n backgroundColor: 'surface',\n borderRadius: 'xl',\n borderWidth: 'default',\n borderStyle: 'solid',\n borderColor: 'borderSubtle',\n});\n\nexport const sidePanelResizable = style({\n minWidth: '360px',\n maxWidth: '50vw',\n});\n\nexport const sidePanelResizer = style([\n sprinkles({\n alignSelf: 'stretch',\n backgroundColor: 'transparent',\n cursor: 'col-resize',\n flex: 'none',\n minWidth: 4,\n position: 'relative',\n width: 4,\n }),\n {\n selectors: {\n '&::after': {\n content: '',\n position: 'absolute',\n top: '50%',\n left: '50%',\n width: '4px',\n height: '96px',\n transform: 'translate(-50%, -50%)',\n borderRadius: vars.borderRadius.full,\n backgroundColor: vars.colors.border,\n boxShadow: vars.boxShadow.sm,\n transitionProperty: 'default',\n transitionDuration: vars.transitionDuration[120],\n transitionTimingFunction: vars.transitionTimingFunction.ease,\n },\n '&:hover::after, &[data-active=\"true\"]::after': {\n backgroundColor: vars.colors.primary,\n boxShadow: `0 0 0 1px ${vars.colors.primaryLight}`,\n },\n '&:focus-visible': {\n outline: `2px solid ${vars.colors.primary}`,\n outlineOffset: '2px',\n },\n },\n },\n]);\n\nexport const sidePanelResizerHiddenOnMobile = sprinkles({\n display: {\n base: 'block',\n max1023: 'none',\n },\n});\n\nexport const header = sprinkles({\n position: 'sticky',\n top: 0,\n zIndex: 10,\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n backgroundColor: 'surface',\n borderWidth: 0,\n borderStyle: 'solid',\n borderBottomWidth: 'default',\n borderBottomColor: 'borderSubtle',\n paddingLeft: 5,\n paddingRight: 5,\n paddingBottom: 2,\n paddingTop: 3,\n});\n\nexport const headerRow = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 4,\n width: 'full',\n});\n\nexport const headerLeading = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 3,\n flex: 1,\n minWidth: 0,\n});\n\nexport const breadcrumbNav = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n minWidth: 0,\n});\n\nexport const breadcrumbList = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: 2,\n rowGap: 1,\n listStyleType: 'none',\n margin: 0,\n padding: 0,\n color: 'textSecondary',\n fontSize: 'xs',\n});\n\nexport const breadcrumbItem = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n maxWidth: '12rem',\n});\n\nexport const breadcrumbLink = style([\n sprinkles({\n color: 'text',\n textDecoration: 'none',\n fontWeight: 'medium',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }),\n {\n selectors: {\n '&:hover': {\n color: vars.colors['blue-600'],\n },\n },\n },\n]);\n\nexport const breadcrumbCurrent = sprinkles({\n color: 'text',\n fontWeight: 'semibold',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\nexport const breadcrumbSeparator = sprinkles({\n color: 'borderLight',\n fontSize: 'xs',\n});\n\nexport const actionGroup = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n gap: 2,\n justifyContent: 'flex-end',\n});\n\nexport const secondaryAction = sprinkles({\n display: 'inline-flex',\n});\n\nexport const tabsRow = sprinkles({\n width: 'full',\n display: 'flex',\n flexWrap: 'wrap',\n gap: 2,\n});\n\nconst tabBase = style([\n sprinkles({\n alignItems: 'center',\n backgroundColor: 'surfaceMuted',\n borderRadius: 'lg',\n color: 'textSecondary',\n display: 'inline-flex',\n fontSize: 'sm',\n fontWeight: 'medium',\n paddingBlock: 1.5,\n paddingInline: 3,\n textDecoration: 'none',\n transitionProperty: 'default',\n transitionDuration: 150,\n transitionTimingFunction: 'ease',\n }),\n {\n selectors: {\n '&:hover': {\n color: vars.colors.text,\n },\n },\n },\n]);\n\nexport const tabRecipe = recipe({\n base: tabBase,\n variants: {\n state: {\n default: {},\n active: sprinkles({\n backgroundColor: 'blue-500',\n color: 'white',\n boxShadow: 'sm',\n }),\n },\n mode: {\n link: {},\n static: sprinkles({\n cursor: 'default',\n }),\n },\n },\n defaultVariants: {\n state: 'default',\n mode: 'link',\n },\n});\n\nexport const content = sprinkles({\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n overflow: 'auto',\n padding: {\n base: 4,\n max1023: 3,\n },\n});\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"PageShell.css.js","names":[],"sources":["../../../../src/components/layout/PageShell.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { recipe } from '@vanilla-extract/recipes';\n\nimport { sprinkles } from '../../theme/sprinkles.css.js';\nimport { vars } from '../../theme/themeContract.js';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 1023px)';\n\nexport const shell = sprinkles({\n display: 'flex',\n width: 'full',\n backgroundColor: 'background',\n backgroundImage: 'pageShellSurface',\n});\n\nexport const page = sprinkles({\n paddingLeft: 2,\n paddingRight: 2,\n paddingTop: 2,\n paddingBottom: 2,\n height: {\n base: 'screen',\n max1023: 'auto',\n },\n flex: 1,\n minWidth: 0,\n});\n\nexport const pageContained = sprinkles({\n height: 'screen',\n minHeight: 0,\n overflow: 'hidden',\n});\n\nexport const pageWithSidePanel = sprinkles({\n display: 'flex',\n alignItems: 'stretch',\n gap: {\n base: 0,\n max1023: 3,\n },\n minWidth: 0,\n flexDirection: {\n base: 'row',\n max1023: 'column',\n },\n height: {\n base: 'full',\n max1023: 'auto',\n },\n});\n\nexport const sidebarColumn = sprinkles({\n position: 'sticky',\n top: 0,\n height: 'screen',\n flexShrink: 0,\n display: 'flex',\n overflow: 'hidden',\n});\n\nexport const sidebarColumnMobile = style({\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n position: 'fixed',\n top: 0,\n left: 0,\n bottom: 0,\n width: '20rem',\n maxWidth: '85vw',\n transform: 'translateX(-100%)',\n transitionProperty: 'transform',\n transitionDuration: vars.transitionDuration[200],\n transitionTimingFunction: vars.transitionTimingFunction.ease,\n zIndex: vars.zIndex[30],\n backgroundColor: vars.colors.surface,\n borderRight: `1px solid ${vars.colors.borderSubtle}`,\n },\n },\n});\n\nexport const sidebarColumnMobileOpen = style({\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n transform: 'translateX(0)',\n },\n },\n});\n\nexport const sidebarInner = style([\n sprinkles({\n display: 'flex',\n height: 'full',\n }),\n {\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n paddingTop: '3.75rem',\n },\n },\n },\n]);\n\nexport const mobileSidebarBackdrop = style({\n display: 'none',\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n display: 'block',\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(15, 23, 42, 0.32)',\n opacity: 0,\n pointerEvents: 'none',\n transitionProperty: 'opacity',\n transitionDuration: vars.transitionDuration[200],\n transitionTimingFunction: vars.transitionTimingFunction.ease,\n zIndex: vars.zIndex[20],\n },\n },\n});\n\nexport const mobileSidebarBackdropOpen = style({\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n opacity: 1,\n pointerEvents: 'auto',\n },\n },\n});\n\nexport const mobileSidebarToggle = sprinkles({\n display: {\n base: 'none',\n max1023: 'inline-flex',\n },\n alignItems: 'center',\n justifyContent: 'center',\n width: 10,\n height: 10,\n borderRadius: 'lg',\n borderStyle: 'solid',\n borderWidth: 'default',\n borderColor: 'border',\n backgroundColor: 'surface',\n color: 'text',\n cursor: 'pointer',\n flexShrink: 0,\n});\n\nexport const desktopSidebarToggle = style([\n sprinkles({\n display: {\n base: 'inline-flex',\n max1023: 'none',\n },\n alignItems: 'center',\n justifyContent: 'center',\n width: 10,\n height: 10,\n borderRadius: 'lg',\n borderStyle: 'solid',\n borderWidth: 'default',\n borderColor: 'border',\n backgroundColor: 'surface',\n color: 'text',\n cursor: 'pointer',\n flexShrink: 0,\n transitionProperty: 'default',\n transitionDuration: 150,\n transitionTimingFunction: 'ease',\n }),\n {\n selectors: {\n '&:hover': {\n borderColor: vars.colors.primaryLight,\n backgroundColor: vars.colors.surfaceMuted,\n color: vars.colors.primary,\n },\n '&:focus-visible': {\n outline: `2px solid ${vars.colors.primary}`,\n outlineOffset: '2px',\n },\n },\n },\n]);\n\nexport const mobileSidebarClose = sprinkles({\n display: {\n base: 'none',\n max1023: 'inline-flex',\n },\n position: {\n base: 'static',\n max1023: 'absolute',\n },\n right: {\n base: 0,\n max1023: 3,\n },\n top: {\n base: 0,\n max1023: 3,\n },\n zIndex: 40,\n alignItems: 'center',\n justifyContent: 'center',\n width: 10,\n height: 10,\n borderRadius: 'lg',\n borderStyle: 'solid',\n borderWidth: 'default',\n borderColor: 'border',\n backgroundColor: 'surface',\n color: 'text',\n cursor: 'pointer',\n});\n\nexport const mainColumn = sprinkles({\n flex: 1,\n height: 'full',\n minWidth: 0,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: 'surface',\n overflow: 'hidden',\n borderRadius: 'lg',\n borderWidth: 'default',\n borderStyle: 'solid',\n borderColor: 'borderSubtle',\n boxShadow: 'inkSoft',\n});\n\nexport const mainColumnContained = sprinkles({\n minHeight: 0,\n overflow: 'hidden',\n});\n\nexport const mainColumnWithSidePanel = sprinkles({\n height: {\n base: 'full',\n max1023: 'auto',\n },\n});\n\nexport const sidePanel = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n minHeight: 0,\n height: {\n base: 'full',\n max1023: 'auto',\n },\n});\n\nexport const sidePanelSurface = sprinkles({\n flex: 'none',\n backgroundColor: 'surface',\n borderRadius: 'xl',\n borderWidth: 'default',\n borderStyle: 'solid',\n borderColor: 'borderSubtle',\n});\n\nexport const sidePanelResizable = style({\n minWidth: '360px',\n maxWidth: '50vw',\n});\n\nexport const sidePanelResizer = style([\n sprinkles({\n alignSelf: 'stretch',\n backgroundColor: 'transparent',\n cursor: 'col-resize',\n flex: 'none',\n minWidth: 4,\n position: 'relative',\n width: 4,\n }),\n {\n selectors: {\n '&::after': {\n content: '',\n position: 'absolute',\n top: '50%',\n left: '50%',\n width: '4px',\n height: '96px',\n transform: 'translate(-50%, -50%)',\n borderRadius: vars.borderRadius.full,\n backgroundColor: vars.colors.border,\n boxShadow: vars.boxShadow.sm,\n transitionProperty: 'default',\n transitionDuration: vars.transitionDuration[120],\n transitionTimingFunction: vars.transitionTimingFunction.ease,\n },\n '&:hover::after, &[data-active=\"true\"]::after': {\n backgroundColor: vars.colors.primary,\n boxShadow: `0 0 0 1px ${vars.colors.primaryLight}`,\n },\n '&:focus-visible': {\n outline: `2px solid ${vars.colors.primary}`,\n outlineOffset: '2px',\n },\n },\n },\n]);\n\nexport const sidePanelResizerHiddenOnMobile = sprinkles({\n display: {\n base: 'block',\n max1023: 'none',\n },\n});\n\nexport const header = sprinkles({\n position: 'sticky',\n top: 0,\n zIndex: 10,\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n backgroundColor: 'surface',\n borderWidth: 0,\n borderStyle: 'solid',\n borderBottomWidth: 'default',\n borderBottomColor: 'borderSubtle',\n paddingLeft: 5,\n paddingRight: 5,\n paddingBottom: 2,\n paddingTop: 3,\n});\n\nexport const headerRow = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 4,\n width: 'full',\n});\n\nexport const headerLeading = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 3,\n flex: 1,\n minWidth: 0,\n});\n\nexport const breadcrumbNav = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n minWidth: 0,\n});\n\nexport const breadcrumbList = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: 2,\n rowGap: 1,\n listStyleType: 'none',\n margin: 0,\n padding: 0,\n color: 'textSecondary',\n fontSize: 'xs',\n});\n\nexport const breadcrumbItem = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n maxWidth: '12rem',\n});\n\nexport const breadcrumbLink = style([\n sprinkles({\n color: 'text',\n textDecoration: 'none',\n fontWeight: 'medium',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }),\n {\n selectors: {\n '&:hover': {\n color: vars.colors['blue-600'],\n },\n },\n },\n]);\n\nexport const breadcrumbCurrent = sprinkles({\n color: 'text',\n fontWeight: 'semibold',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\nexport const breadcrumbSeparator = sprinkles({\n color: 'borderLight',\n fontSize: 'xs',\n});\n\nexport const actionGroup = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n gap: 2,\n justifyContent: 'flex-end',\n});\n\nexport const secondaryAction = sprinkles({\n display: 'inline-flex',\n});\n\nexport const tabsRow = sprinkles({\n width: 'full',\n display: 'flex',\n flexWrap: 'wrap',\n gap: 2,\n});\n\nconst tabBase = style([\n sprinkles({\n alignItems: 'center',\n backgroundColor: 'surfaceMuted',\n borderRadius: 'lg',\n color: 'textSecondary',\n display: 'inline-flex',\n fontSize: 'sm',\n fontWeight: 'medium',\n paddingBlock: 1.5,\n paddingInline: 3,\n textDecoration: 'none',\n transitionProperty: 'default',\n transitionDuration: 150,\n transitionTimingFunction: 'ease',\n }),\n {\n selectors: {\n '&:hover': {\n color: vars.colors.text,\n },\n },\n },\n]);\n\nexport const tabRecipe = recipe({\n base: tabBase,\n variants: {\n state: {\n default: {},\n active: sprinkles({\n backgroundColor: 'blue-500',\n color: 'white',\n boxShadow: 'sm',\n }),\n },\n mode: {\n link: {},\n static: sprinkles({\n cursor: 'default',\n }),\n },\n },\n defaultVariants: {\n state: 'default',\n mode: 'link',\n },\n});\n\nexport const content = sprinkles({\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n overflow: 'auto',\n padding: {\n base: 4,\n max1023: 3,\n },\n});\n\nexport const contentContained = sprinkles({\n overflow: 'hidden',\n minHeight: 0,\n});\n"],"mappings":""}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { cx as e } from "../../theme/tools.js";
|
|
2
2
|
import { useUiTranslation as t } from "../../i18n/useUiTranslation.js";
|
|
3
3
|
import { ModalCloseSvg as n } from "../../icons/ModalCloseSvg.js";
|
|
4
|
-
import { actionGroup as r, breadcrumbCurrent as i, breadcrumbItem as a, breadcrumbLink as o, breadcrumbList as s, breadcrumbNav as c, breadcrumbSeparator as ee, content as te,
|
|
4
|
+
import { actionGroup as r, breadcrumbCurrent as i, breadcrumbItem as a, breadcrumbLink as o, breadcrumbList as s, breadcrumbNav as c, breadcrumbSeparator as ee, content as te, contentContained as ne, header as re, headerLeading as ie, headerRow as ae, mainColumn as oe, mainColumnContained as se, mainColumnWithSidePanel as ce, mobileSidebarBackdrop as le, mobileSidebarBackdropOpen as ue, page as de, pageContained as fe, pageWithSidePanel as pe, secondaryAction as l, shell as me, sidePanel as he, sidePanelResizable as ge, sidePanelResizer as _e, sidePanelResizerHiddenOnMobile as ve, sidePanelSurface as ye, tabRecipe as be, tabsRow as xe } from "./PageShell.css.js";
|
|
5
5
|
import { MenuSvg as u } from "../../icons/MenuSvg.js";
|
|
6
6
|
import { useCallback as d, useEffect as f, useRef as p, useState as m } from "react";
|
|
7
7
|
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
8
8
|
import _ from "@plumile/router/routing/Link.js";
|
|
9
9
|
//#region src/components/layout/PageShell.tsx
|
|
10
|
-
var
|
|
10
|
+
var Se = 520, v = 360, y = .5, b = 480, Ce = 1024, x = "plumile:page-shell:side-panel-width", we = "a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])", S = () => {
|
|
11
11
|
if (typeof window > "u") return null;
|
|
12
12
|
try {
|
|
13
13
|
let e = window.localStorage.getItem(x);
|
|
@@ -24,28 +24,30 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
24
24
|
}, w = (e) => {
|
|
25
25
|
let t = e;
|
|
26
26
|
return typeof window < "u" && (t = window.innerWidth), t * y;
|
|
27
|
-
}, T = (e, t) => typeof e.isActive == "boolean" ? e.isActive : e.href != null && t != null ? t === e.href : !1, E = ({ actions: y, breadcrumb: x, breadcrumbSlot: E, children: D, contentClassName:
|
|
28
|
-
let { t: M } = t(), N = A != null, P =
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
}, T = (e, t) => typeof e.isActive == "boolean" ? e.isActive : e.href != null && t != null ? t === e.href : !1, E = ({ actions: y, breadcrumb: x, breadcrumbSlot: E, children: D, contentClassName: Te, contentScrollMode: Ee = "page", desktopSidebarOpen: O = !0, mobileSidebar: De, onOpenDesktopSidebar: Oe, openDesktopSidebarLabel: ke, sidebar: k, sidePanel: A, tabs: j }) => {
|
|
28
|
+
let { t: M } = t(), N = A != null, P = Ee === "contained", F = null;
|
|
29
|
+
P && (F = ne);
|
|
30
|
+
let I = p(null), L = p(null), R = p(null), z = p(null), B = p(null), V = p(null), [H, U] = m(() => S() ?? Se), W = p(H), [Ae, G] = m(!1), [K, je] = m(!1), [q, J] = m(!1), Y = d(() => {
|
|
31
|
+
J(!1);
|
|
32
|
+
}, []), Me = d(() => {
|
|
31
33
|
if (typeof document < "u") {
|
|
32
34
|
let { activeElement: e } = document;
|
|
33
|
-
e instanceof HTMLElement && (
|
|
35
|
+
e instanceof HTMLElement && (B.current = e);
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
}, []),
|
|
37
|
-
let t =
|
|
37
|
+
J(!0);
|
|
38
|
+
}, []), X = d((e) => {
|
|
39
|
+
let t = I.current;
|
|
38
40
|
if (t == null) return;
|
|
39
41
|
let { width: n } = t.getBoundingClientRect(), r = Math.max(0, Math.min(w(n), n - b)), i = Math.min(v, r);
|
|
40
42
|
r <= 0 && (i = 0);
|
|
41
43
|
let a = Math.max(i, Math.min(e, Math.max(i, r)));
|
|
42
|
-
|
|
43
|
-
}, []),
|
|
44
|
-
if (typeof window > "u" || !N ||
|
|
45
|
-
let t =
|
|
44
|
+
W.current = a, U(a);
|
|
45
|
+
}, []), Z = d((e) => {
|
|
46
|
+
if (typeof window > "u" || !N || K) return;
|
|
47
|
+
let t = I.current;
|
|
46
48
|
if (t == null) return;
|
|
47
|
-
let n = t.getBoundingClientRect(), r =
|
|
48
|
-
|
|
49
|
+
let n = t.getBoundingClientRect(), r = H;
|
|
50
|
+
G(!0);
|
|
49
51
|
let i = (t) => {
|
|
50
52
|
let i = 0;
|
|
51
53
|
if ("touches" in t) {
|
|
@@ -56,54 +58,54 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
56
58
|
let a = r + (e - i), o = Math.max(0, Math.min(w(n.width), n.width - b)), s = Math.min(v, o);
|
|
57
59
|
o <= 0 && (s = 0);
|
|
58
60
|
let c = Math.max(s, Math.min(a, Math.max(s, o)));
|
|
59
|
-
|
|
61
|
+
W.current = c, U(c);
|
|
60
62
|
}, a = () => {
|
|
61
|
-
|
|
62
|
-
let e =
|
|
63
|
-
e?.move != null && (window.removeEventListener("mousemove", e.move), window.removeEventListener("touchmove", e.move)), e?.up != null && (window.removeEventListener("mouseup", e.up), window.removeEventListener("touchend", e.up), window.removeEventListener("touchcancel", e.up)),
|
|
63
|
+
G(!1), C(W.current);
|
|
64
|
+
let e = V.current;
|
|
65
|
+
e?.move != null && (window.removeEventListener("mousemove", e.move), window.removeEventListener("touchmove", e.move)), e?.up != null && (window.removeEventListener("mouseup", e.up), window.removeEventListener("touchend", e.up), window.removeEventListener("touchcancel", e.up)), V.current = null;
|
|
64
66
|
};
|
|
65
|
-
|
|
67
|
+
V.current = {
|
|
66
68
|
move: i,
|
|
67
69
|
up: a
|
|
68
70
|
}, window.addEventListener("mousemove", i), window.addEventListener("touchmove", i, { passive: !1 }), window.addEventListener("mouseup", a), window.addEventListener("touchend", a), window.addEventListener("touchcancel", a);
|
|
69
71
|
}, [
|
|
70
72
|
N,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
K,
|
|
74
|
+
H
|
|
73
75
|
]);
|
|
74
76
|
f(() => {
|
|
75
|
-
|
|
76
|
-
}, [
|
|
77
|
+
W.current = H;
|
|
78
|
+
}, [H]), f(() => {
|
|
77
79
|
if (typeof window > "u") return () => {};
|
|
78
|
-
let e = window.matchMedia(`(max-width: ${
|
|
79
|
-
|
|
80
|
+
let e = window.matchMedia(`(max-width: ${Ce - 1}px)`), t = () => {
|
|
81
|
+
je(e.matches);
|
|
80
82
|
};
|
|
81
83
|
return t(), e.addEventListener("change", t), () => {
|
|
82
84
|
e.removeEventListener("change", t);
|
|
83
85
|
};
|
|
84
86
|
}, []), f(() => {
|
|
85
|
-
N &&
|
|
87
|
+
N && X(H);
|
|
86
88
|
}, [
|
|
87
89
|
N,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
H,
|
|
91
|
+
X
|
|
90
92
|
]), f(() => {
|
|
91
|
-
!
|
|
93
|
+
!K && q && Y();
|
|
92
94
|
}, [
|
|
95
|
+
Y,
|
|
93
96
|
q,
|
|
94
|
-
|
|
95
|
-
W
|
|
97
|
+
K
|
|
96
98
|
]), f(() => {
|
|
97
|
-
if (!
|
|
99
|
+
if (!q) return () => {};
|
|
98
100
|
let e = (e) => {
|
|
99
101
|
if (e.key === "Escape") {
|
|
100
|
-
|
|
102
|
+
Y();
|
|
101
103
|
return;
|
|
102
104
|
}
|
|
103
105
|
if (e.key !== "Tab") return;
|
|
104
|
-
let t =
|
|
106
|
+
let t = L.current;
|
|
105
107
|
if (t == null) return;
|
|
106
|
-
let n = Array.from(t.querySelectorAll(
|
|
108
|
+
let n = Array.from(t.querySelectorAll(we)).filter((e) => e.offsetParent != null || e === document.activeElement), r = n[0], i = n[n.length - 1];
|
|
107
109
|
if (r == null || i == null) {
|
|
108
110
|
e.preventDefault();
|
|
109
111
|
return;
|
|
@@ -113,19 +115,19 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
113
115
|
return;
|
|
114
116
|
}
|
|
115
117
|
!e.shiftKey && document.activeElement === i && (e.preventDefault(), r.focus());
|
|
116
|
-
}, t =
|
|
117
|
-
return
|
|
118
|
+
}, t = R.current;
|
|
119
|
+
return z.current?.focus(), window.addEventListener("keydown", e), () => {
|
|
118
120
|
window.removeEventListener("keydown", e);
|
|
119
|
-
let n =
|
|
120
|
-
n != null && document.contains(n) ? n.focus() : t?.focus(),
|
|
121
|
+
let n = B.current;
|
|
122
|
+
n != null && document.contains(n) ? n.focus() : t?.focus(), B.current = null;
|
|
121
123
|
};
|
|
122
|
-
}, [
|
|
123
|
-
let e =
|
|
124
|
+
}, [Y, q]), f(() => () => {
|
|
125
|
+
let e = V.current;
|
|
124
126
|
e?.move != null && (window.removeEventListener("mousemove", e.move), window.removeEventListener("touchmove", e.move)), e?.up != null && (window.removeEventListener("mouseup", e.up), window.removeEventListener("touchend", e.up), window.removeEventListener("touchcancel", e.up));
|
|
125
127
|
}, []);
|
|
126
|
-
let
|
|
127
|
-
typeof window < "u" && (
|
|
128
|
-
let
|
|
128
|
+
let Q;
|
|
129
|
+
typeof window < "u" && (Q = window.location.pathname);
|
|
130
|
+
let Ne = () => {
|
|
129
131
|
if (E != null) return /* @__PURE__ */ h("div", {
|
|
130
132
|
className: c,
|
|
131
133
|
children: E
|
|
@@ -163,7 +165,7 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
163
165
|
children: e
|
|
164
166
|
})
|
|
165
167
|
});
|
|
166
|
-
},
|
|
168
|
+
}, Pe = () => {
|
|
167
169
|
if (y == null || y.main == null && (y.secondary ?? []).length === 0) return null;
|
|
168
170
|
let e = y.secondary ?? [], t = null;
|
|
169
171
|
return y.main != null && (t = /* @__PURE__ */ h("div", {
|
|
@@ -176,14 +178,14 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
176
178
|
children: e
|
|
177
179
|
}, `secondary-${t}`)), t]
|
|
178
180
|
});
|
|
179
|
-
},
|
|
180
|
-
className:
|
|
181
|
+
}, Fe = () => j == null || j.length === 0 ? null : /* @__PURE__ */ h("div", {
|
|
182
|
+
className: xe,
|
|
181
183
|
children: j.map((e) => {
|
|
182
|
-
let t = T(e,
|
|
184
|
+
let t = T(e, Q), n = "default";
|
|
183
185
|
t && (n = "active");
|
|
184
186
|
let r = "link";
|
|
185
187
|
e.href ?? (r = "static");
|
|
186
|
-
let i =
|
|
188
|
+
let i = be({
|
|
187
189
|
state: n,
|
|
188
190
|
mode: r
|
|
189
191
|
}), a = e.id, o;
|
|
@@ -198,75 +200,75 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
198
200
|
children: e.label
|
|
199
201
|
}, a);
|
|
200
202
|
})
|
|
201
|
-
}),
|
|
202
|
-
if (!
|
|
203
|
+
}), Ie = d((e) => {
|
|
204
|
+
if (!K && (e.key === "ArrowLeft" || e.key === "ArrowRight")) {
|
|
203
205
|
e.preventDefault();
|
|
204
206
|
let t = 16;
|
|
205
|
-
e.key === "ArrowRight" && (t = -16),
|
|
207
|
+
e.key === "ArrowRight" && (t = -16), X(H + t), C(W.current);
|
|
206
208
|
}
|
|
207
209
|
}, [
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
]),
|
|
210
|
+
X,
|
|
211
|
+
K,
|
|
212
|
+
H
|
|
213
|
+
]), Le = null;
|
|
212
214
|
if (N) {
|
|
213
|
-
let t = [
|
|
214
|
-
|
|
215
|
+
let t = [he, ye], n;
|
|
216
|
+
K || (t.push(ge), n = { width: `${H}px` }), Le = /* @__PURE__ */ h("aside", {
|
|
215
217
|
className: e(...t),
|
|
216
218
|
style: n,
|
|
217
219
|
children: A
|
|
218
220
|
});
|
|
219
221
|
}
|
|
220
|
-
let
|
|
222
|
+
let Re = null;
|
|
221
223
|
if (N) {
|
|
222
224
|
let t = "false";
|
|
223
|
-
|
|
224
|
-
let n = v, r = Math.max(v,
|
|
225
|
+
Ae && (t = "true");
|
|
226
|
+
let n = v, r = Math.max(v, H), i = I.current;
|
|
225
227
|
if (i != null) {
|
|
226
228
|
let { width: e } = i.getBoundingClientRect(), t = Math.max(0, Math.min(w(e), e - b));
|
|
227
229
|
n = Math.min(v, t), t <= 0 && (n = 0), r = Math.max(n, t);
|
|
228
230
|
}
|
|
229
|
-
|
|
230
|
-
className: e(
|
|
231
|
+
Re = /* @__PURE__ */ h("div", {
|
|
232
|
+
className: e(_e, ve),
|
|
231
233
|
role: "separator",
|
|
232
234
|
"aria-orientation": "vertical",
|
|
233
235
|
"aria-label": M("layout.pageShell.resizeSidePanel"),
|
|
234
236
|
"aria-valuemin": Math.round(n),
|
|
235
237
|
"aria-valuemax": Math.round(r),
|
|
236
|
-
"aria-valuenow": Math.round(
|
|
238
|
+
"aria-valuenow": Math.round(H),
|
|
237
239
|
tabIndex: 0,
|
|
238
240
|
"data-active": t,
|
|
239
241
|
onMouseDown: (e) => {
|
|
240
|
-
e.preventDefault(),
|
|
242
|
+
e.preventDefault(), Z(e.clientX);
|
|
241
243
|
},
|
|
242
244
|
onTouchStart: (e) => {
|
|
243
245
|
let t = e.touches[0];
|
|
244
|
-
t != null &&
|
|
246
|
+
t != null && Z(t.clientX);
|
|
245
247
|
},
|
|
246
|
-
onKeyDown:
|
|
248
|
+
onKeyDown: Ie
|
|
247
249
|
});
|
|
248
250
|
}
|
|
249
|
-
let
|
|
250
|
-
|
|
251
|
-
let
|
|
251
|
+
let ze = k;
|
|
252
|
+
K && (ze = De ?? k);
|
|
253
|
+
let Be = O || K, $ = ke;
|
|
252
254
|
return $ ??= M("navigation.pageShell.openNavigation"), /* @__PURE__ */ g("div", {
|
|
253
|
-
className:
|
|
255
|
+
className: me,
|
|
254
256
|
children: [
|
|
255
257
|
/* @__PURE__ */ h("div", {
|
|
256
|
-
className: e(
|
|
258
|
+
className: e(le, { [ue]: K && q }),
|
|
257
259
|
"aria-hidden": "true",
|
|
258
|
-
onClick:
|
|
260
|
+
onClick: Y
|
|
259
261
|
}),
|
|
260
|
-
|
|
261
|
-
ref:
|
|
262
|
-
className: e("
|
|
263
|
-
"aria-hidden":
|
|
264
|
-
inert:
|
|
262
|
+
Be && /* @__PURE__ */ g("div", {
|
|
263
|
+
ref: L,
|
|
264
|
+
className: e("_1kley2d4 txvbqbpty txvbqbt7y txvbqbcx7 txvbqbaj7 txvbqb9ip txvbqbl7g", "_1kley2d5", { _1kley2d6: K && q }),
|
|
265
|
+
"aria-hidden": K && !q,
|
|
266
|
+
inert: K && !q,
|
|
265
267
|
children: [/* @__PURE__ */ h("button", {
|
|
266
|
-
ref:
|
|
268
|
+
ref: z,
|
|
267
269
|
type: "button",
|
|
268
|
-
className: "
|
|
269
|
-
onClick:
|
|
270
|
+
className: "_1kley2de txvbqb9hy txvbqb9jn txvbqbpu7 txvbqbpte txvbqbpug txvbqbpve txvbqbt7y txvbqbt8w txvbqbuwg txvbqbcp txvbqbdoy txvbqbtyp txvbqbc7p txvbqb1rp txvbqb1qg txvbqb1cp txvbqbwg txvbqbv41 txvbqbv9z txvbqbv",
|
|
271
|
+
onClick: Y,
|
|
270
272
|
"aria-label": M("navigation.pageShell.closeNavigation"),
|
|
271
273
|
children: /* @__PURE__ */ h(n, {
|
|
272
274
|
width: 18,
|
|
@@ -274,29 +276,35 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
274
276
|
"aria-hidden": "true"
|
|
275
277
|
})
|
|
276
278
|
}), /* @__PURE__ */ h("div", {
|
|
277
|
-
className: "_1kley2d7
|
|
278
|
-
children:
|
|
279
|
+
className: "_1kley2d8 _1kley2d7 txvbqb9ip txvbqbcgg",
|
|
280
|
+
children: ze
|
|
279
281
|
})]
|
|
280
282
|
}),
|
|
281
283
|
/* @__PURE__ */ g("div", {
|
|
282
|
-
ref:
|
|
283
|
-
className: e(
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
ref: I,
|
|
285
|
+
className: e(de, {
|
|
286
|
+
[pe]: N,
|
|
287
|
+
[fe]: P
|
|
288
|
+
}),
|
|
289
|
+
"aria-hidden": K && q,
|
|
290
|
+
inert: K && q,
|
|
286
291
|
children: [
|
|
287
292
|
/* @__PURE__ */ g("div", {
|
|
288
|
-
className: e(
|
|
293
|
+
className: e(oe, {
|
|
294
|
+
[ce]: N,
|
|
295
|
+
[se]: P
|
|
296
|
+
}),
|
|
289
297
|
children: [/* @__PURE__ */ g("div", {
|
|
290
|
-
className:
|
|
298
|
+
className: re,
|
|
291
299
|
children: [/* @__PURE__ */ g("div", {
|
|
292
|
-
className:
|
|
300
|
+
className: ae,
|
|
293
301
|
children: [/* @__PURE__ */ g("div", {
|
|
294
|
-
className:
|
|
302
|
+
className: ie,
|
|
295
303
|
children: [
|
|
296
|
-
!
|
|
304
|
+
!K && !O && /* @__PURE__ */ h("button", {
|
|
297
305
|
type: "button",
|
|
298
|
-
className: "_1kley2dc
|
|
299
|
-
onClick:
|
|
306
|
+
className: "_1kley2dd _1kley2dc txvbqb9jg txvbqb9i5 txvbqbcp txvbqbdoy txvbqbtyp txvbqbc7p txvbqb1rp txvbqb1qg txvbqb1cp txvbqbwg txvbqbv41 txvbqbv9z txvbqbv txvbqbaj7 txvbqb77 txvbqb6x txvbqb7k",
|
|
307
|
+
onClick: Oe,
|
|
300
308
|
"aria-label": $,
|
|
301
309
|
title: $,
|
|
302
310
|
children: /* @__PURE__ */ h(u, {
|
|
@@ -305,12 +313,12 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
305
313
|
"aria-hidden": "true"
|
|
306
314
|
})
|
|
307
315
|
}),
|
|
308
|
-
|
|
309
|
-
ref:
|
|
316
|
+
K && /* @__PURE__ */ h("button", {
|
|
317
|
+
ref: R,
|
|
310
318
|
type: "button",
|
|
311
|
-
className: "
|
|
312
|
-
onClick:
|
|
313
|
-
"aria-expanded":
|
|
319
|
+
className: "_1kley2db txvbqb9hy txvbqb9jn txvbqbcp txvbqbdoy txvbqbtyp txvbqbc7p txvbqb1rp txvbqb1qg txvbqb1cp txvbqbwg txvbqbv41 txvbqbv9z txvbqbv txvbqbaj7",
|
|
320
|
+
onClick: Me,
|
|
321
|
+
"aria-expanded": q,
|
|
314
322
|
"aria-label": M("navigation.pageShell.openNavigation"),
|
|
315
323
|
children: /* @__PURE__ */ h(u, {
|
|
316
324
|
width: 18,
|
|
@@ -318,17 +326,17 @@ var ye = 520, v = 360, y = .5, b = 480, be = 1024, x = "plumile:page-shell:side-
|
|
|
318
326
|
"aria-hidden": "true"
|
|
319
327
|
})
|
|
320
328
|
}),
|
|
321
|
-
|
|
329
|
+
Ne()
|
|
322
330
|
]
|
|
323
|
-
}),
|
|
324
|
-
}),
|
|
331
|
+
}), Pe()]
|
|
332
|
+
}), Fe()]
|
|
325
333
|
}), /* @__PURE__ */ h("div", {
|
|
326
|
-
className: e(te,
|
|
334
|
+
className: e(te, F, Te),
|
|
327
335
|
children: D
|
|
328
336
|
})]
|
|
329
337
|
}),
|
|
330
|
-
|
|
331
|
-
|
|
338
|
+
Re,
|
|
339
|
+
Le
|
|
332
340
|
]
|
|
333
341
|
})
|
|
334
342
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageShell.js","names":[],"sources":["../../../../src/components/layout/PageShell.tsx"],"sourcesContent":["import Link from '@plumile/router/routing/Link.js';\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type JSX,\n type ReactNode,\n type KeyboardEvent,\n type CSSProperties,\n} from 'react';\n\nimport * as styles from './PageShell.css.js';\nimport { MenuSvg } from '../../icons/MenuSvg.js';\nimport { ModalCloseSvg } from '../../icons/ModalCloseSvg.js';\nimport { cx } from '../../theme/tools.js';\nimport { useUiTranslation } from '../../i18n/useUiTranslation.js';\n\nexport type BreadcrumbItem = {\n label: ReactNode;\n href?: string;\n};\n\nexport type PageShellTab = {\n id: string;\n label: ReactNode;\n href?: string;\n isActive?: boolean;\n};\n\nexport type PageShellActions = {\n main?: ReactNode;\n secondary?: ReactNode[];\n};\n\nconst DEFAULT_SIDE_PANEL_WIDTH = 520;\nconst MIN_SIDE_PANEL_WIDTH = 360;\nconst MAX_SIDE_PANEL_RATIO = 0.5;\nconst MIN_MAIN_WIDTH = 480;\nconst SPLIT_BREAKPOINT = 1024;\nconst SIDE_PANEL_WIDTH_STORAGE_KEY = 'plumile:page-shell:side-panel-width';\nconst FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nconst readStoredSidePanelWidth = (): number | null => {\n if (typeof window === 'undefined') {\n return null;\n }\n\n try {\n const stored = window.localStorage.getItem(SIDE_PANEL_WIDTH_STORAGE_KEY);\n if (stored == null) {\n return null;\n }\n const parsed = Number(stored);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst persistSidePanelWidth = (width: number): void => {\n if (typeof window === 'undefined') {\n return;\n }\n\n try {\n window.localStorage.setItem(SIDE_PANEL_WIDTH_STORAGE_KEY, String(width));\n } catch {\n // ignore quota / permission errors\n }\n};\n\nconst resolveMaxSidePanelWidth = (containerWidth: number): number => {\n let viewWidth = containerWidth;\n if (typeof window !== 'undefined') {\n viewWidth = window.innerWidth;\n }\n return viewWidth * MAX_SIDE_PANEL_RATIO;\n};\n\ntype ResizeMoveHandler = (event: MouseEvent | TouchEvent) => void;\ntype ResizeUpHandler = () => void;\ntype ActiveResizeHandlers = {\n move?: ResizeMoveHandler | null;\n up?: ResizeUpHandler | null;\n};\n\ntype Props = {\n sidebar: ReactNode;\n mobileSidebar?: ReactNode;\n desktopSidebarOpen?: boolean;\n onOpenDesktopSidebar?: () => void;\n openDesktopSidebarLabel?: string;\n children: ReactNode;\n breadcrumb?: BreadcrumbItem[];\n breadcrumbSlot?: ReactNode;\n tabs?: PageShellTab[];\n actions?: PageShellActions;\n sidePanel?: ReactNode;\n contentClassName?: string;\n};\n\nconst resolveIsActive = (tab: PageShellTab, pathname?: string): boolean => {\n if (typeof tab.isActive === 'boolean') {\n return tab.isActive;\n }\n\n if (tab.href != null && pathname != null) {\n return pathname === tab.href;\n }\n\n return false;\n};\n\nexport const PageShell = ({\n actions,\n breadcrumb,\n breadcrumbSlot,\n children,\n contentClassName,\n desktopSidebarOpen = true,\n mobileSidebar,\n onOpenDesktopSidebar,\n openDesktopSidebarLabel,\n sidebar,\n sidePanel,\n tabs,\n}: Props): JSX.Element => {\n const { t } = useUiTranslation();\n const hasSidePanel = sidePanel != null;\n const pageRef = useRef<HTMLDivElement | null>(null);\n const mobileSidebarRef = useRef<HTMLDivElement | null>(null);\n const mobileSidebarToggleRef = useRef<HTMLButtonElement | null>(null);\n const mobileSidebarCloseRef = useRef<HTMLButtonElement | null>(null);\n const mobileSidebarPreviousFocusRef = useRef<HTMLElement | null>(null);\n const activeResizeHandlersRef = useRef<ActiveResizeHandlers | null>(null);\n const [sidePanelWidth, setSidePanelWidth] = useState(() => {\n const stored = readStoredSidePanelWidth();\n return stored ?? DEFAULT_SIDE_PANEL_WIDTH;\n });\n const sidePanelWidthSnapshotRef = useRef(sidePanelWidth);\n const [isResizingPanel, setIsResizingPanel] = useState(false);\n const [isStackedLayout, setIsStackedLayout] = useState(false);\n const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);\n\n const closeMobileSidebar = useCallback(() => {\n setIsMobileSidebarOpen(false);\n }, []);\n\n const openMobileSidebar = useCallback(() => {\n if (typeof document !== 'undefined') {\n const { activeElement } = document;\n if (activeElement instanceof HTMLElement) {\n mobileSidebarPreviousFocusRef.current = activeElement;\n }\n }\n setIsMobileSidebarOpen(true);\n }, []);\n\n const clampSidePanelWidth = useCallback((candidateWidth: number): void => {\n const container = pageRef.current;\n if (container == null) {\n return;\n }\n\n const { width } = container.getBoundingClientRect();\n const maxWidth = Math.max(\n 0,\n Math.min(resolveMaxSidePanelWidth(width), width - MIN_MAIN_WIDTH),\n );\n const minWidth = Math.min(MIN_SIDE_PANEL_WIDTH, maxWidth);\n let safeMin = minWidth;\n if (maxWidth <= 0) {\n safeMin = 0;\n }\n const safeMax = Math.max(safeMin, maxWidth);\n const clampedWidth = Math.max(safeMin, Math.min(candidateWidth, safeMax));\n sidePanelWidthSnapshotRef.current = clampedWidth;\n setSidePanelWidth(clampedWidth);\n }, []);\n\n const startResizing = useCallback(\n (startClientX: number): void => {\n if (typeof window === 'undefined') {\n return;\n }\n\n if (!hasSidePanel || isStackedLayout) {\n return;\n }\n\n const container = pageRef.current;\n if (container == null) {\n return;\n }\n\n const rect = container.getBoundingClientRect();\n const currentWidth = sidePanelWidth;\n setIsResizingPanel(true);\n\n const moveHandler: ResizeMoveHandler = (event) => {\n let clientX = 0;\n if ('touches' in event) {\n const touch = event.touches[0];\n if (touch == null) {\n return;\n }\n clientX = touch.clientX;\n } else {\n clientX = event.clientX;\n }\n\n const deltaX = startClientX - clientX;\n const nextWidth = currentWidth + deltaX;\n\n const maxWidth = Math.max(\n 0,\n Math.min(\n resolveMaxSidePanelWidth(rect.width),\n rect.width - MIN_MAIN_WIDTH,\n ),\n );\n const minWidth = Math.min(MIN_SIDE_PANEL_WIDTH, maxWidth);\n let safeMin = minWidth;\n if (maxWidth <= 0) {\n safeMin = 0;\n }\n const safeMax = Math.max(safeMin, maxWidth);\n\n const clampedWidth = Math.max(safeMin, Math.min(nextWidth, safeMax));\n sidePanelWidthSnapshotRef.current = clampedWidth;\n setSidePanelWidth(clampedWidth);\n };\n\n const upHandler: ResizeUpHandler = () => {\n setIsResizingPanel(false);\n persistSidePanelWidth(sidePanelWidthSnapshotRef.current);\n const handlers = activeResizeHandlersRef.current;\n if (handlers?.move != null) {\n window.removeEventListener('mousemove', handlers.move);\n window.removeEventListener('touchmove', handlers.move);\n }\n if (handlers?.up != null) {\n window.removeEventListener('mouseup', handlers.up);\n window.removeEventListener('touchend', handlers.up);\n window.removeEventListener('touchcancel', handlers.up);\n }\n activeResizeHandlersRef.current = null;\n };\n\n activeResizeHandlersRef.current = { move: moveHandler, up: upHandler };\n\n window.addEventListener('mousemove', moveHandler);\n window.addEventListener('touchmove', moveHandler, { passive: false });\n window.addEventListener('mouseup', upHandler);\n window.addEventListener('touchend', upHandler);\n window.addEventListener('touchcancel', upHandler);\n },\n [hasSidePanel, isStackedLayout, sidePanelWidth],\n );\n\n useEffect(() => {\n sidePanelWidthSnapshotRef.current = sidePanelWidth;\n }, [sidePanelWidth]);\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return () => {};\n }\n const mediaQuery = window.matchMedia(\n `(max-width: ${SPLIT_BREAKPOINT - 1}px)`,\n );\n const handleMediaChange = () => {\n setIsStackedLayout(mediaQuery.matches);\n };\n\n handleMediaChange();\n mediaQuery.addEventListener('change', handleMediaChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleMediaChange);\n };\n }, []);\n\n useEffect(() => {\n if (hasSidePanel) {\n clampSidePanelWidth(sidePanelWidth);\n }\n }, [hasSidePanel, sidePanelWidth, clampSidePanelWidth]);\n\n useEffect(() => {\n if (!isStackedLayout && isMobileSidebarOpen) {\n closeMobileSidebar();\n }\n }, [closeMobileSidebar, isMobileSidebarOpen, isStackedLayout]);\n\n useEffect(() => {\n if (!isMobileSidebarOpen) {\n return () => {};\n }\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n closeMobileSidebar();\n return;\n }\n\n if (event.key !== 'Tab') {\n return;\n }\n\n const sidebarElement = mobileSidebarRef.current;\n if (sidebarElement == null) {\n return;\n }\n\n const focusableElements = Array.from(\n sidebarElement.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).filter((element) => {\n return (\n element.offsetParent != null || element === document.activeElement\n );\n });\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n if (firstElement == null || lastElement == null) {\n event.preventDefault();\n return;\n }\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n return;\n }\n\n if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n };\n\n const fallbackFocusElement = mobileSidebarToggleRef.current;\n mobileSidebarCloseRef.current?.focus();\n\n window.addEventListener('keydown', handleEscape);\n return () => {\n window.removeEventListener('keydown', handleEscape);\n const previousFocus = mobileSidebarPreviousFocusRef.current;\n if (previousFocus != null && document.contains(previousFocus)) {\n previousFocus.focus();\n } else {\n fallbackFocusElement?.focus();\n }\n mobileSidebarPreviousFocusRef.current = null;\n };\n }, [closeMobileSidebar, isMobileSidebarOpen]);\n\n useEffect(() => {\n return () => {\n const handlers = activeResizeHandlersRef.current;\n if (handlers?.move != null) {\n window.removeEventListener('mousemove', handlers.move);\n window.removeEventListener('touchmove', handlers.move);\n }\n if (handlers?.up != null) {\n window.removeEventListener('mouseup', handlers.up);\n window.removeEventListener('touchend', handlers.up);\n window.removeEventListener('touchcancel', handlers.up);\n }\n };\n }, []);\n\n let currentPath: string | undefined;\n if (typeof window !== 'undefined') {\n currentPath = window.location.pathname;\n }\n\n const renderBreadcrumb = (): JSX.Element | null => {\n if (breadcrumbSlot != null) {\n return <div className={styles.breadcrumbNav}>{breadcrumbSlot}</div>;\n }\n\n if (breadcrumb == null || breadcrumb.length === 0) {\n return null;\n }\n\n const items = breadcrumb.flatMap((item, index) => {\n const isLast = index === breadcrumb.length - 1;\n const key = `${item.href ?? 'crumb'}-${index}`;\n let content: JSX.Element;\n if (item.href != null && !isLast) {\n content = (\n <Link to={item.href} className={styles.breadcrumbLink}>\n {item.label}\n </Link>\n );\n } else {\n let breadcrumbClass = styles.breadcrumbLink;\n if (isLast) {\n breadcrumbClass = styles.breadcrumbCurrent;\n }\n content = <span className={breadcrumbClass}>{item.label}</span>;\n }\n\n const renderedItem = (\n <li key={key} className={styles.breadcrumbItem}>\n {content}\n </li>\n );\n\n if (isLast) {\n return [renderedItem];\n }\n\n return [\n renderedItem,\n <li\n key={`${key}-sep`}\n className={styles.breadcrumbSeparator}\n aria-hidden=\"true\"\n >\n /\n </li>,\n ];\n });\n\n return (\n <nav\n className={styles.breadcrumbNav}\n aria-label={t('navigation.breadcrumb')}\n >\n <ol className={styles.breadcrumbList}>{items}</ol>\n </nav>\n );\n };\n\n const renderActions = (): JSX.Element | null => {\n if (\n actions == null ||\n (actions.main == null && (actions.secondary ?? []).length === 0)\n ) {\n return null;\n }\n\n const secondaryNodes = actions.secondary ?? [];\n\n let mainActionNode: JSX.Element | null = null;\n if (actions.main != null) {\n mainActionNode = (\n <div className={styles.secondaryAction}>{actions.main}</div>\n );\n }\n\n return (\n <div className={styles.actionGroup}>\n {secondaryNodes.map((node, index) => {\n return (\n <div key={`secondary-${index}`} className={styles.secondaryAction}>\n {node}\n </div>\n );\n })}\n {mainActionNode}\n </div>\n );\n };\n\n const renderTabs = (): JSX.Element | null => {\n if (tabs == null || tabs.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.tabsRow}>\n {tabs.map((tab) => {\n const isActive = resolveIsActive(tab, currentPath);\n let tabState: 'default' | 'active' = 'default';\n if (isActive) {\n tabState = 'active';\n }\n let tabMode: 'static' | 'link' = 'link';\n if (tab.href == null) {\n tabMode = 'static';\n }\n const className = styles.tabRecipe({\n state: tabState,\n mode: tabMode,\n });\n const key = tab.id;\n let ariaCurrent: 'page' | undefined;\n if (isActive) {\n ariaCurrent = 'page';\n }\n\n if (tab.href != null) {\n return (\n <Link\n key={key}\n to={tab.href}\n className={className}\n aria-current={ariaCurrent}\n >\n {tab.label}\n </Link>\n );\n }\n\n return (\n <span key={key} className={className} aria-current={ariaCurrent}>\n {tab.label}\n </span>\n );\n })}\n </div>\n );\n };\n\n const handleResizerKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n if (isStackedLayout) {\n return;\n }\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n let delta = 16;\n if (event.key === 'ArrowRight') {\n delta = -16;\n }\n clampSidePanelWidth(sidePanelWidth + delta);\n persistSidePanelWidth(sidePanelWidthSnapshotRef.current);\n }\n },\n [clampSidePanelWidth, isStackedLayout, sidePanelWidth],\n );\n\n let sidePanelNode: JSX.Element | null = null;\n if (hasSidePanel) {\n const sidePanelClasses = [styles.sidePanel, styles.sidePanelSurface];\n let sidePanelStyle: CSSProperties | undefined;\n if (!isStackedLayout) {\n sidePanelClasses.push(styles.sidePanelResizable);\n sidePanelStyle = {\n width: `${sidePanelWidth}px`,\n };\n }\n sidePanelNode = (\n <aside className={cx(...sidePanelClasses)} style={sidePanelStyle}>\n {sidePanel}\n </aside>\n );\n }\n\n let resizerNode: JSX.Element | null = null;\n if (hasSidePanel) {\n let resizerActive = 'false';\n if (isResizingPanel) {\n resizerActive = 'true';\n }\n let resizerMin = MIN_SIDE_PANEL_WIDTH;\n let resizerMax = Math.max(MIN_SIDE_PANEL_WIDTH, sidePanelWidth);\n const pageElement = pageRef.current;\n if (pageElement != null) {\n const { width } = pageElement.getBoundingClientRect();\n const maxWidth = Math.max(\n 0,\n Math.min(resolveMaxSidePanelWidth(width), width - MIN_MAIN_WIDTH),\n );\n resizerMin = Math.min(MIN_SIDE_PANEL_WIDTH, maxWidth);\n if (maxWidth <= 0) {\n resizerMin = 0;\n }\n resizerMax = Math.max(resizerMin, maxWidth);\n }\n resizerNode = (\n <div\n className={cx(\n styles.sidePanelResizer,\n styles.sidePanelResizerHiddenOnMobile,\n )}\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={t('layout.pageShell.resizeSidePanel')}\n aria-valuemin={Math.round(resizerMin)}\n aria-valuemax={Math.round(resizerMax)}\n aria-valuenow={Math.round(sidePanelWidth)}\n tabIndex={0}\n data-active={resizerActive}\n onMouseDown={(event) => {\n event.preventDefault();\n startResizing(event.clientX);\n }}\n onTouchStart={(event) => {\n const touch = event.touches[0];\n if (touch != null) {\n startResizing(touch.clientX);\n }\n }}\n onKeyDown={handleResizerKeyDown}\n />\n );\n }\n\n let sidebarContent = sidebar;\n if (isStackedLayout) {\n sidebarContent = mobileSidebar ?? sidebar;\n }\n const shouldRenderDesktopSidebar = desktopSidebarOpen || isStackedLayout;\n let resolvedOpenDesktopSidebarLabel = openDesktopSidebarLabel;\n resolvedOpenDesktopSidebarLabel ??= t('navigation.pageShell.openNavigation');\n\n return (\n <div className={styles.shell}>\n <div\n className={cx(styles.mobileSidebarBackdrop, {\n [styles.mobileSidebarBackdropOpen]:\n isStackedLayout && isMobileSidebarOpen,\n })}\n aria-hidden=\"true\"\n onClick={closeMobileSidebar}\n />\n {shouldRenderDesktopSidebar && (\n <div\n ref={mobileSidebarRef}\n className={cx(styles.sidebarColumn, styles.sidebarColumnMobile, {\n [styles.sidebarColumnMobileOpen]:\n isStackedLayout && isMobileSidebarOpen,\n })}\n aria-hidden={isStackedLayout && !isMobileSidebarOpen}\n inert={isStackedLayout && !isMobileSidebarOpen}\n >\n <button\n ref={mobileSidebarCloseRef}\n type=\"button\"\n className={styles.mobileSidebarClose}\n onClick={closeMobileSidebar}\n aria-label={t('navigation.pageShell.closeNavigation')}\n >\n <ModalCloseSvg width={18} height={18} aria-hidden=\"true\" />\n </button>\n <div className={styles.sidebarInner}>{sidebarContent}</div>\n </div>\n )}\n <div\n ref={pageRef}\n className={cx(styles.page, {\n [styles.pageWithSidePanel]: hasSidePanel,\n })}\n aria-hidden={isStackedLayout && isMobileSidebarOpen}\n inert={isStackedLayout && isMobileSidebarOpen}\n >\n <div\n className={cx(styles.mainColumn, {\n [styles.mainColumnWithSidePanel]: hasSidePanel,\n })}\n >\n <div className={styles.header}>\n <div className={styles.headerRow}>\n <div className={styles.headerLeading}>\n {!isStackedLayout && !desktopSidebarOpen && (\n <button\n type=\"button\"\n className={styles.desktopSidebarToggle}\n onClick={onOpenDesktopSidebar}\n aria-label={resolvedOpenDesktopSidebarLabel}\n title={resolvedOpenDesktopSidebarLabel}\n >\n <MenuSvg width={18} height={18} aria-hidden=\"true\" />\n </button>\n )}\n {isStackedLayout && (\n <button\n ref={mobileSidebarToggleRef}\n type=\"button\"\n className={styles.mobileSidebarToggle}\n onClick={openMobileSidebar}\n aria-expanded={isMobileSidebarOpen}\n aria-label={t('navigation.pageShell.openNavigation')}\n >\n <MenuSvg width={18} height={18} aria-hidden=\"true\" />\n </button>\n )}\n {renderBreadcrumb()}\n </div>\n {renderActions()}\n </div>\n {renderTabs()}\n </div>\n <div className={cx(styles.content, contentClassName)}>{children}</div>\n </div>\n {resizerNode}\n {sidePanelNode}\n </div>\n </div>\n );\n};\n\nexport const __test = {\n readStoredSidePanelWidth,\n resolveMaxSidePanelWidth,\n resolveIsActive,\n} as const;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PageShell.js","names":[],"sources":["../../../../src/components/layout/PageShell.tsx"],"sourcesContent":["import Link from '@plumile/router/routing/Link.js';\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type JSX,\n type ReactNode,\n type KeyboardEvent,\n type CSSProperties,\n} from 'react';\n\nimport * as styles from './PageShell.css.js';\nimport { MenuSvg } from '../../icons/MenuSvg.js';\nimport { ModalCloseSvg } from '../../icons/ModalCloseSvg.js';\nimport { cx } from '../../theme/tools.js';\nimport { useUiTranslation } from '../../i18n/useUiTranslation.js';\n\nexport type BreadcrumbItem = {\n label: ReactNode;\n href?: string;\n};\n\nexport type PageShellTab = {\n id: string;\n label: ReactNode;\n href?: string;\n isActive?: boolean;\n};\n\nexport type PageShellActions = {\n main?: ReactNode;\n secondary?: ReactNode[];\n};\n\nexport type PageShellContentScrollMode = 'page' | 'contained';\n\nconst DEFAULT_SIDE_PANEL_WIDTH = 520;\nconst MIN_SIDE_PANEL_WIDTH = 360;\nconst MAX_SIDE_PANEL_RATIO = 0.5;\nconst MIN_MAIN_WIDTH = 480;\nconst SPLIT_BREAKPOINT = 1024;\nconst SIDE_PANEL_WIDTH_STORAGE_KEY = 'plumile:page-shell:side-panel-width';\nconst FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nconst readStoredSidePanelWidth = (): number | null => {\n if (typeof window === 'undefined') {\n return null;\n }\n\n try {\n const stored = window.localStorage.getItem(SIDE_PANEL_WIDTH_STORAGE_KEY);\n if (stored == null) {\n return null;\n }\n const parsed = Number(stored);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst persistSidePanelWidth = (width: number): void => {\n if (typeof window === 'undefined') {\n return;\n }\n\n try {\n window.localStorage.setItem(SIDE_PANEL_WIDTH_STORAGE_KEY, String(width));\n } catch {\n // ignore quota / permission errors\n }\n};\n\nconst resolveMaxSidePanelWidth = (containerWidth: number): number => {\n let viewWidth = containerWidth;\n if (typeof window !== 'undefined') {\n viewWidth = window.innerWidth;\n }\n return viewWidth * MAX_SIDE_PANEL_RATIO;\n};\n\ntype ResizeMoveHandler = (event: MouseEvent | TouchEvent) => void;\ntype ResizeUpHandler = () => void;\ntype ActiveResizeHandlers = {\n move?: ResizeMoveHandler | null;\n up?: ResizeUpHandler | null;\n};\n\ntype Props = {\n sidebar: ReactNode;\n mobileSidebar?: ReactNode;\n desktopSidebarOpen?: boolean;\n onOpenDesktopSidebar?: () => void;\n openDesktopSidebarLabel?: string;\n children: ReactNode;\n breadcrumb?: BreadcrumbItem[];\n breadcrumbSlot?: ReactNode;\n tabs?: PageShellTab[];\n actions?: PageShellActions;\n sidePanel?: ReactNode;\n contentClassName?: string;\n contentScrollMode?: PageShellContentScrollMode;\n};\n\nconst resolveIsActive = (tab: PageShellTab, pathname?: string): boolean => {\n if (typeof tab.isActive === 'boolean') {\n return tab.isActive;\n }\n\n if (tab.href != null && pathname != null) {\n return pathname === tab.href;\n }\n\n return false;\n};\n\nexport const PageShell = ({\n actions,\n breadcrumb,\n breadcrumbSlot,\n children,\n contentClassName,\n contentScrollMode = 'page',\n desktopSidebarOpen = true,\n mobileSidebar,\n onOpenDesktopSidebar,\n openDesktopSidebarLabel,\n sidebar,\n sidePanel,\n tabs,\n}: Props): JSX.Element => {\n const { t } = useUiTranslation();\n const hasSidePanel = sidePanel != null;\n const isContainedScroll = contentScrollMode === 'contained';\n let containedContentClassName: string | null = null;\n if (isContainedScroll) {\n containedContentClassName = styles.contentContained;\n }\n const pageRef = useRef<HTMLDivElement | null>(null);\n const mobileSidebarRef = useRef<HTMLDivElement | null>(null);\n const mobileSidebarToggleRef = useRef<HTMLButtonElement | null>(null);\n const mobileSidebarCloseRef = useRef<HTMLButtonElement | null>(null);\n const mobileSidebarPreviousFocusRef = useRef<HTMLElement | null>(null);\n const activeResizeHandlersRef = useRef<ActiveResizeHandlers | null>(null);\n const [sidePanelWidth, setSidePanelWidth] = useState(() => {\n const stored = readStoredSidePanelWidth();\n return stored ?? DEFAULT_SIDE_PANEL_WIDTH;\n });\n const sidePanelWidthSnapshotRef = useRef(sidePanelWidth);\n const [isResizingPanel, setIsResizingPanel] = useState(false);\n const [isStackedLayout, setIsStackedLayout] = useState(false);\n const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);\n\n const closeMobileSidebar = useCallback(() => {\n setIsMobileSidebarOpen(false);\n }, []);\n\n const openMobileSidebar = useCallback(() => {\n if (typeof document !== 'undefined') {\n const { activeElement } = document;\n if (activeElement instanceof HTMLElement) {\n mobileSidebarPreviousFocusRef.current = activeElement;\n }\n }\n setIsMobileSidebarOpen(true);\n }, []);\n\n const clampSidePanelWidth = useCallback((candidateWidth: number): void => {\n const container = pageRef.current;\n if (container == null) {\n return;\n }\n\n const { width } = container.getBoundingClientRect();\n const maxWidth = Math.max(\n 0,\n Math.min(resolveMaxSidePanelWidth(width), width - MIN_MAIN_WIDTH),\n );\n const minWidth = Math.min(MIN_SIDE_PANEL_WIDTH, maxWidth);\n let safeMin = minWidth;\n if (maxWidth <= 0) {\n safeMin = 0;\n }\n const safeMax = Math.max(safeMin, maxWidth);\n const clampedWidth = Math.max(safeMin, Math.min(candidateWidth, safeMax));\n sidePanelWidthSnapshotRef.current = clampedWidth;\n setSidePanelWidth(clampedWidth);\n }, []);\n\n const startResizing = useCallback(\n (startClientX: number): void => {\n if (typeof window === 'undefined') {\n return;\n }\n\n if (!hasSidePanel || isStackedLayout) {\n return;\n }\n\n const container = pageRef.current;\n if (container == null) {\n return;\n }\n\n const rect = container.getBoundingClientRect();\n const currentWidth = sidePanelWidth;\n setIsResizingPanel(true);\n\n const moveHandler: ResizeMoveHandler = (event) => {\n let clientX = 0;\n if ('touches' in event) {\n const touch = event.touches[0];\n if (touch == null) {\n return;\n }\n clientX = touch.clientX;\n } else {\n clientX = event.clientX;\n }\n\n const deltaX = startClientX - clientX;\n const nextWidth = currentWidth + deltaX;\n\n const maxWidth = Math.max(\n 0,\n Math.min(\n resolveMaxSidePanelWidth(rect.width),\n rect.width - MIN_MAIN_WIDTH,\n ),\n );\n const minWidth = Math.min(MIN_SIDE_PANEL_WIDTH, maxWidth);\n let safeMin = minWidth;\n if (maxWidth <= 0) {\n safeMin = 0;\n }\n const safeMax = Math.max(safeMin, maxWidth);\n\n const clampedWidth = Math.max(safeMin, Math.min(nextWidth, safeMax));\n sidePanelWidthSnapshotRef.current = clampedWidth;\n setSidePanelWidth(clampedWidth);\n };\n\n const upHandler: ResizeUpHandler = () => {\n setIsResizingPanel(false);\n persistSidePanelWidth(sidePanelWidthSnapshotRef.current);\n const handlers = activeResizeHandlersRef.current;\n if (handlers?.move != null) {\n window.removeEventListener('mousemove', handlers.move);\n window.removeEventListener('touchmove', handlers.move);\n }\n if (handlers?.up != null) {\n window.removeEventListener('mouseup', handlers.up);\n window.removeEventListener('touchend', handlers.up);\n window.removeEventListener('touchcancel', handlers.up);\n }\n activeResizeHandlersRef.current = null;\n };\n\n activeResizeHandlersRef.current = { move: moveHandler, up: upHandler };\n\n window.addEventListener('mousemove', moveHandler);\n window.addEventListener('touchmove', moveHandler, { passive: false });\n window.addEventListener('mouseup', upHandler);\n window.addEventListener('touchend', upHandler);\n window.addEventListener('touchcancel', upHandler);\n },\n [hasSidePanel, isStackedLayout, sidePanelWidth],\n );\n\n useEffect(() => {\n sidePanelWidthSnapshotRef.current = sidePanelWidth;\n }, [sidePanelWidth]);\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return () => {};\n }\n const mediaQuery = window.matchMedia(\n `(max-width: ${SPLIT_BREAKPOINT - 1}px)`,\n );\n const handleMediaChange = () => {\n setIsStackedLayout(mediaQuery.matches);\n };\n\n handleMediaChange();\n mediaQuery.addEventListener('change', handleMediaChange);\n\n return () => {\n mediaQuery.removeEventListener('change', handleMediaChange);\n };\n }, []);\n\n useEffect(() => {\n if (hasSidePanel) {\n clampSidePanelWidth(sidePanelWidth);\n }\n }, [hasSidePanel, sidePanelWidth, clampSidePanelWidth]);\n\n useEffect(() => {\n if (!isStackedLayout && isMobileSidebarOpen) {\n closeMobileSidebar();\n }\n }, [closeMobileSidebar, isMobileSidebarOpen, isStackedLayout]);\n\n useEffect(() => {\n if (!isMobileSidebarOpen) {\n return () => {};\n }\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n closeMobileSidebar();\n return;\n }\n\n if (event.key !== 'Tab') {\n return;\n }\n\n const sidebarElement = mobileSidebarRef.current;\n if (sidebarElement == null) {\n return;\n }\n\n const focusableElements = Array.from(\n sidebarElement.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).filter((element) => {\n return (\n element.offsetParent != null || element === document.activeElement\n );\n });\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n if (firstElement == null || lastElement == null) {\n event.preventDefault();\n return;\n }\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n return;\n }\n\n if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n };\n\n const fallbackFocusElement = mobileSidebarToggleRef.current;\n mobileSidebarCloseRef.current?.focus();\n\n window.addEventListener('keydown', handleEscape);\n return () => {\n window.removeEventListener('keydown', handleEscape);\n const previousFocus = mobileSidebarPreviousFocusRef.current;\n if (previousFocus != null && document.contains(previousFocus)) {\n previousFocus.focus();\n } else {\n fallbackFocusElement?.focus();\n }\n mobileSidebarPreviousFocusRef.current = null;\n };\n }, [closeMobileSidebar, isMobileSidebarOpen]);\n\n useEffect(() => {\n return () => {\n const handlers = activeResizeHandlersRef.current;\n if (handlers?.move != null) {\n window.removeEventListener('mousemove', handlers.move);\n window.removeEventListener('touchmove', handlers.move);\n }\n if (handlers?.up != null) {\n window.removeEventListener('mouseup', handlers.up);\n window.removeEventListener('touchend', handlers.up);\n window.removeEventListener('touchcancel', handlers.up);\n }\n };\n }, []);\n\n let currentPath: string | undefined;\n if (typeof window !== 'undefined') {\n currentPath = window.location.pathname;\n }\n\n const renderBreadcrumb = (): JSX.Element | null => {\n if (breadcrumbSlot != null) {\n return <div className={styles.breadcrumbNav}>{breadcrumbSlot}</div>;\n }\n\n if (breadcrumb == null || breadcrumb.length === 0) {\n return null;\n }\n\n const items = breadcrumb.flatMap((item, index) => {\n const isLast = index === breadcrumb.length - 1;\n const key = `${item.href ?? 'crumb'}-${index}`;\n let content: JSX.Element;\n if (item.href != null && !isLast) {\n content = (\n <Link to={item.href} className={styles.breadcrumbLink}>\n {item.label}\n </Link>\n );\n } else {\n let breadcrumbClass = styles.breadcrumbLink;\n if (isLast) {\n breadcrumbClass = styles.breadcrumbCurrent;\n }\n content = <span className={breadcrumbClass}>{item.label}</span>;\n }\n\n const renderedItem = (\n <li key={key} className={styles.breadcrumbItem}>\n {content}\n </li>\n );\n\n if (isLast) {\n return [renderedItem];\n }\n\n return [\n renderedItem,\n <li\n key={`${key}-sep`}\n className={styles.breadcrumbSeparator}\n aria-hidden=\"true\"\n >\n /\n </li>,\n ];\n });\n\n return (\n <nav\n className={styles.breadcrumbNav}\n aria-label={t('navigation.breadcrumb')}\n >\n <ol className={styles.breadcrumbList}>{items}</ol>\n </nav>\n );\n };\n\n const renderActions = (): JSX.Element | null => {\n if (\n actions == null ||\n (actions.main == null && (actions.secondary ?? []).length === 0)\n ) {\n return null;\n }\n\n const secondaryNodes = actions.secondary ?? [];\n\n let mainActionNode: JSX.Element | null = null;\n if (actions.main != null) {\n mainActionNode = (\n <div className={styles.secondaryAction}>{actions.main}</div>\n );\n }\n\n return (\n <div className={styles.actionGroup}>\n {secondaryNodes.map((node, index) => {\n return (\n <div key={`secondary-${index}`} className={styles.secondaryAction}>\n {node}\n </div>\n );\n })}\n {mainActionNode}\n </div>\n );\n };\n\n const renderTabs = (): JSX.Element | null => {\n if (tabs == null || tabs.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.tabsRow}>\n {tabs.map((tab) => {\n const isActive = resolveIsActive(tab, currentPath);\n let tabState: 'default' | 'active' = 'default';\n if (isActive) {\n tabState = 'active';\n }\n let tabMode: 'static' | 'link' = 'link';\n if (tab.href == null) {\n tabMode = 'static';\n }\n const className = styles.tabRecipe({\n state: tabState,\n mode: tabMode,\n });\n const key = tab.id;\n let ariaCurrent: 'page' | undefined;\n if (isActive) {\n ariaCurrent = 'page';\n }\n\n if (tab.href != null) {\n return (\n <Link\n key={key}\n to={tab.href}\n className={className}\n aria-current={ariaCurrent}\n >\n {tab.label}\n </Link>\n );\n }\n\n return (\n <span key={key} className={className} aria-current={ariaCurrent}>\n {tab.label}\n </span>\n );\n })}\n </div>\n );\n };\n\n const handleResizerKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n if (isStackedLayout) {\n return;\n }\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n let delta = 16;\n if (event.key === 'ArrowRight') {\n delta = -16;\n }\n clampSidePanelWidth(sidePanelWidth + delta);\n persistSidePanelWidth(sidePanelWidthSnapshotRef.current);\n }\n },\n [clampSidePanelWidth, isStackedLayout, sidePanelWidth],\n );\n\n let sidePanelNode: JSX.Element | null = null;\n if (hasSidePanel) {\n const sidePanelClasses = [styles.sidePanel, styles.sidePanelSurface];\n let sidePanelStyle: CSSProperties | undefined;\n if (!isStackedLayout) {\n sidePanelClasses.push(styles.sidePanelResizable);\n sidePanelStyle = {\n width: `${sidePanelWidth}px`,\n };\n }\n sidePanelNode = (\n <aside className={cx(...sidePanelClasses)} style={sidePanelStyle}>\n {sidePanel}\n </aside>\n );\n }\n\n let resizerNode: JSX.Element | null = null;\n if (hasSidePanel) {\n let resizerActive = 'false';\n if (isResizingPanel) {\n resizerActive = 'true';\n }\n let resizerMin = MIN_SIDE_PANEL_WIDTH;\n let resizerMax = Math.max(MIN_SIDE_PANEL_WIDTH, sidePanelWidth);\n const pageElement = pageRef.current;\n if (pageElement != null) {\n const { width } = pageElement.getBoundingClientRect();\n const maxWidth = Math.max(\n 0,\n Math.min(resolveMaxSidePanelWidth(width), width - MIN_MAIN_WIDTH),\n );\n resizerMin = Math.min(MIN_SIDE_PANEL_WIDTH, maxWidth);\n if (maxWidth <= 0) {\n resizerMin = 0;\n }\n resizerMax = Math.max(resizerMin, maxWidth);\n }\n resizerNode = (\n <div\n className={cx(\n styles.sidePanelResizer,\n styles.sidePanelResizerHiddenOnMobile,\n )}\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={t('layout.pageShell.resizeSidePanel')}\n aria-valuemin={Math.round(resizerMin)}\n aria-valuemax={Math.round(resizerMax)}\n aria-valuenow={Math.round(sidePanelWidth)}\n tabIndex={0}\n data-active={resizerActive}\n onMouseDown={(event) => {\n event.preventDefault();\n startResizing(event.clientX);\n }}\n onTouchStart={(event) => {\n const touch = event.touches[0];\n if (touch != null) {\n startResizing(touch.clientX);\n }\n }}\n onKeyDown={handleResizerKeyDown}\n />\n );\n }\n\n let sidebarContent = sidebar;\n if (isStackedLayout) {\n sidebarContent = mobileSidebar ?? sidebar;\n }\n const shouldRenderDesktopSidebar = desktopSidebarOpen || isStackedLayout;\n let resolvedOpenDesktopSidebarLabel = openDesktopSidebarLabel;\n resolvedOpenDesktopSidebarLabel ??= t('navigation.pageShell.openNavigation');\n\n return (\n <div className={styles.shell}>\n <div\n className={cx(styles.mobileSidebarBackdrop, {\n [styles.mobileSidebarBackdropOpen]:\n isStackedLayout && isMobileSidebarOpen,\n })}\n aria-hidden=\"true\"\n onClick={closeMobileSidebar}\n />\n {shouldRenderDesktopSidebar && (\n <div\n ref={mobileSidebarRef}\n className={cx(styles.sidebarColumn, styles.sidebarColumnMobile, {\n [styles.sidebarColumnMobileOpen]:\n isStackedLayout && isMobileSidebarOpen,\n })}\n aria-hidden={isStackedLayout && !isMobileSidebarOpen}\n inert={isStackedLayout && !isMobileSidebarOpen}\n >\n <button\n ref={mobileSidebarCloseRef}\n type=\"button\"\n className={styles.mobileSidebarClose}\n onClick={closeMobileSidebar}\n aria-label={t('navigation.pageShell.closeNavigation')}\n >\n <ModalCloseSvg width={18} height={18} aria-hidden=\"true\" />\n </button>\n <div className={styles.sidebarInner}>{sidebarContent}</div>\n </div>\n )}\n <div\n ref={pageRef}\n className={cx(styles.page, {\n [styles.pageWithSidePanel]: hasSidePanel,\n [styles.pageContained]: isContainedScroll,\n })}\n aria-hidden={isStackedLayout && isMobileSidebarOpen}\n inert={isStackedLayout && isMobileSidebarOpen}\n >\n <div\n className={cx(styles.mainColumn, {\n [styles.mainColumnWithSidePanel]: hasSidePanel,\n [styles.mainColumnContained]: isContainedScroll,\n })}\n >\n <div className={styles.header}>\n <div className={styles.headerRow}>\n <div className={styles.headerLeading}>\n {!isStackedLayout && !desktopSidebarOpen && (\n <button\n type=\"button\"\n className={styles.desktopSidebarToggle}\n onClick={onOpenDesktopSidebar}\n aria-label={resolvedOpenDesktopSidebarLabel}\n title={resolvedOpenDesktopSidebarLabel}\n >\n <MenuSvg width={18} height={18} aria-hidden=\"true\" />\n </button>\n )}\n {isStackedLayout && (\n <button\n ref={mobileSidebarToggleRef}\n type=\"button\"\n className={styles.mobileSidebarToggle}\n onClick={openMobileSidebar}\n aria-expanded={isMobileSidebarOpen}\n aria-label={t('navigation.pageShell.openNavigation')}\n >\n <MenuSvg width={18} height={18} aria-hidden=\"true\" />\n </button>\n )}\n {renderBreadcrumb()}\n </div>\n {renderActions()}\n </div>\n {renderTabs()}\n </div>\n <div\n className={cx(\n styles.content,\n containedContentClassName,\n contentClassName,\n )}\n >\n {children}\n </div>\n </div>\n {resizerNode}\n {sidePanelNode}\n </div>\n </div>\n );\n};\n\nexport const __test = {\n readStoredSidePanelWidth,\n resolveMaxSidePanelWidth,\n resolveIsActive,\n} as const;\n"],"mappings":"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"}
|