@box/blueprint-web 8.8.1 → 9.0.0
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/index.css +178 -46
- package/lib-esm/index.d.ts +1 -0
- package/lib-esm/index.js +2 -0
- package/lib-esm/page/index.d.ts +30 -6
- package/lib-esm/page/index.js +39 -0
- package/lib-esm/page/page-context.d.ts +11 -19
- package/lib-esm/page/page-context.js +50 -0
- package/lib-esm/page/page-global-header-search-container.js +19 -0
- package/lib-esm/page/page-global-header-side-content-container.js +18 -0
- package/lib-esm/page/page-global-header.d.ts +3 -3
- package/lib-esm/page/page-global-header.js +39 -0
- package/lib-esm/page/page-main-section-content.d.ts +2 -0
- package/lib-esm/page/page-main-section-content.js +17 -0
- package/lib-esm/page/page-main-section-sidebar.d.ts +2 -0
- package/lib-esm/page/page-main-section-sidebar.js +27 -0
- package/lib-esm/page/page-main-section.d.ts +6 -0
- package/lib-esm/page/page-main-section.js +23 -0
- package/lib-esm/page/page-navigation.js +84 -0
- package/lib-esm/page/page-page-header.d.ts +6 -0
- package/lib-esm/page/page-page-header.js +18 -0
- package/lib-esm/page/page-root.d.ts +2 -2
- package/lib-esm/page/page-root.js +100 -0
- package/lib-esm/page/page-subnavigation.d.ts +2 -0
- package/lib-esm/page/page-subnavigation.js +15 -0
- package/lib-esm/page/page.module.js +4 -0
- package/lib-esm/page/types.d.ts +22 -12
- package/lib-esm/primitives/page-header/page-header.d.ts +4 -4
- package/lib-esm/primitives/page-header/page-header.js +8 -8
- package/lib-esm/primitives/page-header/types.d.ts +13 -4
- package/lib-esm/utils/fast-context.d.ts +8 -0
- package/lib-esm/utils/fast-context.js +68 -0
- package/lib-esm/utils/useRefWithEffect.d.ts +6 -0
- package/lib-esm/utils/useRefWithEffect.js +25 -0
- package/package.json +4 -4
- package/lib-esm/page/page-content.d.ts +0 -2
- package/lib-esm/utils/createSetRefWithCallback.d.ts +0 -10
package/lib-esm/index.css
CHANGED
|
@@ -4171,6 +4171,184 @@ table.bp_inline_table_module_inlineTable--b023b tr:not(:last-child) td{
|
|
|
4171
4171
|
margin-block:var(--space-2);
|
|
4172
4172
|
}
|
|
4173
4173
|
|
|
4174
|
+
.bp_page_module_page--47219{
|
|
4175
|
+
--navigation-width-collapsed:var(--space-20);
|
|
4176
|
+
--navigation-width-expanded:calc(var(--space-20)*3);
|
|
4177
|
+
--large-viewport-inline-space:var(--space-8);
|
|
4178
|
+
display:flex;
|
|
4179
|
+
flex-direction:column;
|
|
4180
|
+
height:calc(100vh - var(--space-5));
|
|
4181
|
+
overflow:hidden;
|
|
4182
|
+
padding-block-start:var(--space-5);
|
|
4183
|
+
padding-inline-start:var(--navigation-width-collapsed);
|
|
4184
|
+
position:relative;
|
|
4185
|
+
}
|
|
4186
|
+
.bp_page_module_page--47219 .bp_page_module_globalHeader--47219{
|
|
4187
|
+
align-items:center;
|
|
4188
|
+
display:flex;
|
|
4189
|
+
flex-direction:row;
|
|
4190
|
+
justify-content:space-between;
|
|
4191
|
+
padding-inline:var(--large-viewport-inline-space);
|
|
4192
|
+
position:relative;
|
|
4193
|
+
}
|
|
4194
|
+
.bp_page_module_page--47219 .bp_page_module_globalHeader--47219 .bp_page_module_searchContainer--47219,.bp_page_module_page--47219 .bp_page_module_globalHeader--47219 .bp_page_module_sideContentContainer--47219{
|
|
4195
|
+
display:flex;
|
|
4196
|
+
flex:none;
|
|
4197
|
+
}
|
|
4198
|
+
.bp_page_module_page--47219 .bp_page_module_pageMain--47219{
|
|
4199
|
+
display:flex;
|
|
4200
|
+
flex-direction:column;
|
|
4201
|
+
height:inherit;
|
|
4202
|
+
overflow:hidden;
|
|
4203
|
+
padding-block-start:var(--space-5);
|
|
4204
|
+
padding-inline:var(--large-viewport-inline-space);
|
|
4205
|
+
}
|
|
4206
|
+
.bp_page_module_page--47219 .bp_page_module_pageMain--47219 .bp_page_module_topSection--47219{
|
|
4207
|
+
display:flex;
|
|
4208
|
+
flex-direction:column;
|
|
4209
|
+
flex-shrink:0;
|
|
4210
|
+
gap:var(--space-5);
|
|
4211
|
+
overflow:hidden;
|
|
4212
|
+
}
|
|
4213
|
+
.bp_page_module_page--47219 .bp_page_module_pageMain--47219 .bp_page_module_mainSection--47219{
|
|
4214
|
+
display:flex;
|
|
4215
|
+
flex-direction:row;
|
|
4216
|
+
height:inherit;
|
|
4217
|
+
overflow:hidden;
|
|
4218
|
+
}
|
|
4219
|
+
.bp_page_module_page--47219 .bp_page_module_pageMain--47219 .bp_page_module_mainSection--47219 .bp_page_module_content--47219{
|
|
4220
|
+
flex-grow:1;
|
|
4221
|
+
margin-block-start:var(--space-4);
|
|
4222
|
+
overflow-y:auto;
|
|
4223
|
+
padding-inline-end:var(--space-8);
|
|
4224
|
+
}
|
|
4225
|
+
.bp_page_module_page--47219 .bp_page_module_pageMain--47219 .bp_page_module_mainSection--47219 .bp_page_module_sidebar--47219{
|
|
4226
|
+
flex-shrink:0;
|
|
4227
|
+
margin-inline-start:var(--space-4);
|
|
4228
|
+
}
|
|
4229
|
+
.bp_page_module_page--47219 .bp_page_module_navigationPortal--47219{
|
|
4230
|
+
background-color:var(--box-blue-100);
|
|
4231
|
+
height:100%;
|
|
4232
|
+
left:0;
|
|
4233
|
+
position:absolute;
|
|
4234
|
+
top:0;
|
|
4235
|
+
width:var(--navigation-width);
|
|
4236
|
+
}
|
|
4237
|
+
.bp_page_module_page--47219 .bp_page_module_navigationPortal--47219 .bp_page_module_navigationContent--47219{
|
|
4238
|
+
height:100%;
|
|
4239
|
+
}
|
|
4240
|
+
.bp_page_module_page--47219 .bp_page_module_navigationPortalLargeCollapsed--47219{
|
|
4241
|
+
--navigation-width:var(--navigation-width-collapsed);
|
|
4242
|
+
}
|
|
4243
|
+
.bp_page_module_page--47219 .bp_page_module_navigationPortalLargeExpanded--47219{
|
|
4244
|
+
--navigation-width:var(--navigation-width-expanded);
|
|
4245
|
+
}
|
|
4246
|
+
|
|
4247
|
+
.bp_page_module_hide--47219{
|
|
4248
|
+
visibility:hidden;
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
.bp_page_module_pageMediumOrLessViewport--47219{
|
|
4252
|
+
--global-header-fixed-size-section-height:var(--space-16);
|
|
4253
|
+
--global-header-fixed-size-section-collapsed:var(--space-16);
|
|
4254
|
+
height:calc(100vh - var(--global-header-fixed-size-section-height));
|
|
4255
|
+
padding-block-start:var(--global-header-fixed-size-section-height);
|
|
4256
|
+
padding-inline-start:0;
|
|
4257
|
+
}
|
|
4258
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_globalHeader--47219{
|
|
4259
|
+
height:var(--global-header-fixed-size-section-height);
|
|
4260
|
+
left:0;
|
|
4261
|
+
padding-inline:0;
|
|
4262
|
+
padding-inline-start:var(--global-header-fixed-size-section-collapsed);
|
|
4263
|
+
position:fixed;
|
|
4264
|
+
top:0;
|
|
4265
|
+
width:calc(100vw - var(--global-header-fixed-size-section-collapsed));
|
|
4266
|
+
}
|
|
4267
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_globalHeader--47219 .bp_page_module_search--47219{
|
|
4268
|
+
width:var(--global-header-fixed-size-section-collapsed);
|
|
4269
|
+
}
|
|
4270
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_pageMain--47219{
|
|
4271
|
+
overflow-y:auto;
|
|
4272
|
+
padding-inline:var(--space-4);
|
|
4273
|
+
}
|
|
4274
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_pageMain--47219 .bp_page_module_mainSection--47219{
|
|
4275
|
+
overflow:unset;
|
|
4276
|
+
}
|
|
4277
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_pageMain--47219 .bp_page_module_mainSection--47219 .bp_page_module_content--47219{
|
|
4278
|
+
overflow-y:unset;
|
|
4279
|
+
}
|
|
4280
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_navigationPortalOverlayCollapsed--47219{
|
|
4281
|
+
height:100%;
|
|
4282
|
+
}
|
|
4283
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_navigationPortalOverlayCollapsed--47219 .bp_page_module_navigationContent--47219{
|
|
4284
|
+
width:var(--global-header-fixed-size-section-collapsed);
|
|
4285
|
+
}
|
|
4286
|
+
.bp_page_module_pageMediumOrLessViewport--47219 .bp_page_module_navigationPortalOverlayExpanded--47219{
|
|
4287
|
+
height:100vh;
|
|
4288
|
+
width:100vw;
|
|
4289
|
+
z-index:1;
|
|
4290
|
+
}
|
|
4291
|
+
|
|
4292
|
+
.bp_page_module_pageNavigationXXLargeCollapsed--47219{
|
|
4293
|
+
--navigation-width:var(--navigation-width-collapsed);
|
|
4294
|
+
padding-inline-start:var(--navigation-width-collapsed);
|
|
4295
|
+
}
|
|
4296
|
+
|
|
4297
|
+
.bp_page_module_pageNavigationXXLargeExpanded--47219{
|
|
4298
|
+
--navigation-width:var(--navigation-width-expanded);
|
|
4299
|
+
padding-inline-start:var(--navigation-width-expanded);
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4302
|
+
.bp_page_module_portalEntry--47219{
|
|
4303
|
+
display:contents;
|
|
4304
|
+
}
|
|
4305
|
+
|
|
4306
|
+
.bp_page_header_module_pageHeader--d031a{
|
|
4307
|
+
align-items:center;
|
|
4308
|
+
background:var(--surface-surface);
|
|
4309
|
+
display:flex;
|
|
4310
|
+
flex-direction:row;
|
|
4311
|
+
justify-content:space-between;
|
|
4312
|
+
max-height:var(--size-16);
|
|
4313
|
+
min-height:var(--size-10);
|
|
4314
|
+
width:100%;
|
|
4315
|
+
}
|
|
4316
|
+
.bp_page_header_module_pageHeader--d031a.bp_page_header_module_sticky--d031a{
|
|
4317
|
+
bottom:var(--blueprint-page-header-bottom, 0);
|
|
4318
|
+
left:var(--blueprint-page-header-left, 0);
|
|
4319
|
+
position:sticky;
|
|
4320
|
+
right:var(--blueprint-page-header-right, 0);
|
|
4321
|
+
top:var(--blueprint-page-header-top, 0);
|
|
4322
|
+
}
|
|
4323
|
+
.bp_page_header_module_pageHeader--d031a.bp_page_header_module_default--d031a{
|
|
4324
|
+
height:var(--size-16);
|
|
4325
|
+
padding-inline:var(--space-2);
|
|
4326
|
+
}
|
|
4327
|
+
.bp_page_header_module_pageHeader--d031a.bp_page_header_module_inline--d031a{
|
|
4328
|
+
height:var(--size-10);
|
|
4329
|
+
}
|
|
4330
|
+
.bp_page_header_module_pageHeader--d031a .bp_page_header_module_corner--d031a{
|
|
4331
|
+
align-items:center;
|
|
4332
|
+
display:flex;
|
|
4333
|
+
flex-basis:content;
|
|
4334
|
+
flex-grow:0;
|
|
4335
|
+
flex-shrink:0;
|
|
4336
|
+
}
|
|
4337
|
+
.bp_page_header_module_pageHeader--d031a .bp_page_header_module_startElements--d031a{
|
|
4338
|
+
align-items:center;
|
|
4339
|
+
display:flex;
|
|
4340
|
+
flex-grow:1;
|
|
4341
|
+
justify-content:flex-start;
|
|
4342
|
+
overflow:hidden;
|
|
4343
|
+
}
|
|
4344
|
+
.bp_page_header_module_pageHeader--d031a .bp_page_header_module_endElements--d031a{
|
|
4345
|
+
align-items:center;
|
|
4346
|
+
display:flex;
|
|
4347
|
+
flex-direction:row;
|
|
4348
|
+
flex-grow:1;
|
|
4349
|
+
justify-content:flex-end;
|
|
4350
|
+
}
|
|
4351
|
+
|
|
4174
4352
|
.bp_page_section_module_pageSectionContainer--2add7{
|
|
4175
4353
|
display:flex;
|
|
4176
4354
|
flex-direction:column;
|
|
@@ -4697,52 +4875,6 @@ table.bp_inline_table_module_inlineTable--b023b tr:not(:last-child) td{
|
|
|
4697
4875
|
fill:currentColor;
|
|
4698
4876
|
}
|
|
4699
4877
|
|
|
4700
|
-
.bp_page_header_module_pageHeader--d031a{
|
|
4701
|
-
align-items:center;
|
|
4702
|
-
background:var(--surface-surface);
|
|
4703
|
-
display:flex;
|
|
4704
|
-
flex-direction:row;
|
|
4705
|
-
justify-content:space-between;
|
|
4706
|
-
max-height:var(--size-16);
|
|
4707
|
-
min-height:var(--size-10);
|
|
4708
|
-
width:100%;
|
|
4709
|
-
}
|
|
4710
|
-
.bp_page_header_module_pageHeader--d031a.bp_page_header_module_sticky--d031a{
|
|
4711
|
-
bottom:var(--blueprint-page-header-bottom, 0);
|
|
4712
|
-
left:var(--blueprint-page-header-left, 0);
|
|
4713
|
-
position:sticky;
|
|
4714
|
-
right:var(--blueprint-page-header-right, 0);
|
|
4715
|
-
top:var(--blueprint-page-header-top, 0);
|
|
4716
|
-
}
|
|
4717
|
-
.bp_page_header_module_pageHeader--d031a.bp_page_header_module_default--d031a{
|
|
4718
|
-
height:var(--size-16);
|
|
4719
|
-
padding-inline:var(--space-2);
|
|
4720
|
-
}
|
|
4721
|
-
.bp_page_header_module_pageHeader--d031a.bp_page_header_module_inline--d031a{
|
|
4722
|
-
height:var(--size-10);
|
|
4723
|
-
}
|
|
4724
|
-
.bp_page_header_module_pageHeader--d031a .bp_page_header_module_corner--d031a{
|
|
4725
|
-
align-items:center;
|
|
4726
|
-
display:flex;
|
|
4727
|
-
flex-basis:content;
|
|
4728
|
-
flex-grow:0;
|
|
4729
|
-
flex-shrink:0;
|
|
4730
|
-
}
|
|
4731
|
-
.bp_page_header_module_pageHeader--d031a .bp_page_header_module_startElements--d031a{
|
|
4732
|
-
align-items:center;
|
|
4733
|
-
display:flex;
|
|
4734
|
-
flex-grow:1;
|
|
4735
|
-
justify-content:flex-start;
|
|
4736
|
-
overflow:hidden;
|
|
4737
|
-
}
|
|
4738
|
-
.bp_page_header_module_pageHeader--d031a .bp_page_header_module_endElements--d031a{
|
|
4739
|
-
align-items:center;
|
|
4740
|
-
display:flex;
|
|
4741
|
-
flex-direction:row;
|
|
4742
|
-
flex-grow:1;
|
|
4743
|
-
justify-content:flex-end;
|
|
4744
|
-
}
|
|
4745
|
-
|
|
4746
4878
|
.bp_popover_module_popoverMainContent--7fad3{
|
|
4747
4879
|
mask-image:linear-gradient(to top, #0000, var(--gray-black)), linear-gradient(to left, #0000 var(--space-4), var(--gray-black) var(--space-4));
|
|
4748
4880
|
overflow-y:auto;
|
package/lib-esm/index.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export * from './list-item/list-item';
|
|
|
30
30
|
export * from './loading-indicator/loading-indicator';
|
|
31
31
|
export * from './modal';
|
|
32
32
|
export * from './navigation-menu';
|
|
33
|
+
export * from './page';
|
|
33
34
|
export * from './page-section';
|
|
34
35
|
export * from './password-input';
|
|
35
36
|
export * from './primitives/calendar';
|
package/lib-esm/index.js
CHANGED
|
@@ -34,6 +34,7 @@ export { ActionCell, Cell, Column, DropIndicator, Row, Table, TableBody, TableHe
|
|
|
34
34
|
export { LoadingIndicator } from './loading-indicator/loading-indicator.js';
|
|
35
35
|
export { Modal } from './modal/modal.js';
|
|
36
36
|
export { NavigationMenu } from './navigation-menu/index.js';
|
|
37
|
+
export { Page } from './page/index.js';
|
|
37
38
|
export { PageSection } from './page-section/index.js';
|
|
38
39
|
export { PasswordInput } from './password-input/password-input.js';
|
|
39
40
|
export { Calendar } from './primitives/calendar/calendar.js';
|
|
@@ -89,5 +90,6 @@ export { Breakpoint, useBreakpoint } from './utils/useBreakpoint.js';
|
|
|
89
90
|
export { useFullTextTooltip } from './utils/useFullTextTooltip.js';
|
|
90
91
|
export { getUniqueId, useUniqueId } from './utils/useUniqueId.js';
|
|
91
92
|
export { VisuallyHidden } from './visually-hidden/visually-hidden.js';
|
|
93
|
+
export { useMainSectionSidebar, usePageNavigation } from './page/page-context.js';
|
|
92
94
|
export { useNotification } from './primitives/notification/notification-provider.js';
|
|
93
95
|
export { useTabs } from './primitives/tabs/use-tabs.js';
|
package/lib-esm/page/index.d.ts
CHANGED
|
@@ -1,16 +1,40 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { useMainSectionSidebar, usePageNavigation } from './page-context';
|
|
2
2
|
export * from './types';
|
|
3
|
-
export declare const Page: import("react").ForwardRefExoticComponent<import("./types").
|
|
3
|
+
export declare const Page: import("react").ForwardRefExoticComponent<import("./types").PageLayoutProps & import("react").RefAttributes<HTMLDivElement>> & {
|
|
4
|
+
/**
|
|
5
|
+
* Top level navigation landmark on the left side of the page.
|
|
6
|
+
*/
|
|
4
7
|
Navigation: import("react").ForwardRefExoticComponent<import("./types").PageNavigationProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
5
8
|
/**
|
|
6
|
-
* Top level
|
|
7
|
-
*
|
|
9
|
+
* Top level header landmark placed at the top of the page.
|
|
10
|
+
* It should contain two subcomponents:
|
|
8
11
|
* - PageGlobalHeader.SearchContainer
|
|
9
12
|
* - PageGlobalHeader.SideContentContainer
|
|
10
13
|
*/
|
|
11
|
-
GlobalHeader: import("react").ForwardRefExoticComponent<import("./types").
|
|
14
|
+
GlobalHeader: import("react").ForwardRefExoticComponent<import("./types").PageGlobalHeaderProps & import("react").RefAttributes<HTMLDivElement>> & {
|
|
12
15
|
SearchContainer: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
13
16
|
SideContentContainer: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
14
17
|
};
|
|
15
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Main content area of the page.
|
|
20
|
+
* Contains two subcomponents:
|
|
21
|
+
* - Page.MainContent.ContentScrollableSection
|
|
22
|
+
* - Page.MainContent.Complementary (sidebar-like section with hide/show functionality)
|
|
23
|
+
*/
|
|
24
|
+
MainSection: import("react").ForwardRefExoticComponent<import("./types").PageMainSectionProps & import("react").RefAttributes<HTMLDivElement>> & {
|
|
25
|
+
Content: import("react").ForwardRefExoticComponent<import("./types").PageMainProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
26
|
+
Sidebar: import("react").ForwardRefExoticComponent<import("./types").PageMainSectionSidebarProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Sub navigation area of the page.
|
|
30
|
+
*/
|
|
31
|
+
SubNavigation: import("react").ForwardRefExoticComponent<import("./types").PageSubNavigationProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
32
|
+
/**
|
|
33
|
+
* Page header with title and actions.
|
|
34
|
+
*/
|
|
35
|
+
PageHeader: ((props: import("./types").PagePageHeaderProps) => import("react/jsx-runtime").JSX.Element) & {
|
|
36
|
+
StartElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
37
|
+
EndElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
38
|
+
Corner: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
39
|
+
};
|
|
16
40
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PageGlobalHeader } from './page-global-header.js';
|
|
2
|
+
import { MainSection } from './page-main-section.js';
|
|
3
|
+
import { PageNavigation } from './page-navigation.js';
|
|
4
|
+
import { PagePageHeader } from './page-page-header.js';
|
|
5
|
+
import { PageRoot } from './page-root.js';
|
|
6
|
+
import { PageSubNavigation } from './page-subnavigation.js';
|
|
7
|
+
import 'react/jsx-runtime';
|
|
8
|
+
import 'react';
|
|
9
|
+
|
|
10
|
+
const Page = Object.assign(PageRoot, {
|
|
11
|
+
/**
|
|
12
|
+
* Top level navigation landmark on the left side of the page.
|
|
13
|
+
*/
|
|
14
|
+
Navigation: PageNavigation,
|
|
15
|
+
/**
|
|
16
|
+
* Top level header landmark placed at the top of the page.
|
|
17
|
+
* It should contain two subcomponents:
|
|
18
|
+
* - PageGlobalHeader.SearchContainer
|
|
19
|
+
* - PageGlobalHeader.SideContentContainer
|
|
20
|
+
*/
|
|
21
|
+
GlobalHeader: PageGlobalHeader,
|
|
22
|
+
/**
|
|
23
|
+
* Main content area of the page.
|
|
24
|
+
* Contains two subcomponents:
|
|
25
|
+
* - Page.MainContent.ContentScrollableSection
|
|
26
|
+
* - Page.MainContent.Complementary (sidebar-like section with hide/show functionality)
|
|
27
|
+
*/
|
|
28
|
+
MainSection,
|
|
29
|
+
/**
|
|
30
|
+
* Sub navigation area of the page.
|
|
31
|
+
*/
|
|
32
|
+
SubNavigation: PageSubNavigation,
|
|
33
|
+
/**
|
|
34
|
+
* Page header with title and actions.
|
|
35
|
+
*/
|
|
36
|
+
PageHeader: PagePageHeader
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export { Page };
|
|
@@ -1,27 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
export interface PageContextValuesType {
|
|
1
|
+
export interface PageFastContextValuesType {
|
|
3
2
|
navigationExpanded: boolean;
|
|
4
|
-
setNavigationExpanded: (expanded: boolean) => void;
|
|
5
|
-
toggleNavigationExpanded: () => void;
|
|
6
3
|
pageContainer: HTMLElement | null;
|
|
7
|
-
setPageContainer: (container: HTMLDivElement | null) => void;
|
|
8
4
|
globalHeaderContainer: HTMLDivElement | null;
|
|
9
|
-
|
|
5
|
+
mainSectionSidebarVisible: boolean;
|
|
10
6
|
}
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
defaultNavigationExpanded: boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Callback called when the navigation is toggled
|
|
18
|
-
* */
|
|
19
|
-
onToggleNavigationExpanded?: (nextState: boolean) => void;
|
|
20
|
-
}
|
|
21
|
-
export declare const PageContext: import("react").Context<PageContextValuesType | null>;
|
|
22
|
-
export declare const PageContextProvider: ({ children, onToggleNavigationExpanded, defaultNavigationExpanded, }: PropsWithChildren<PageContextProps>) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
-
export declare const usePage: () => {
|
|
7
|
+
export declare const PageProvider: ({ children }: {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}) => import("react/jsx-runtime").JSX.Element, usePageStore: <SelectorOutput>(selector: (store: PageFastContextValuesType) => SelectorOutput) => [SelectorOutput, (value: Partial<PageFastContextValuesType>) => void], usePageStoreSetter: () => (value: Partial<PageFastContextValuesType>) => void;
|
|
10
|
+
export declare const usePageNavigation: () => {
|
|
24
11
|
navigationExpanded: boolean;
|
|
25
12
|
setNavigationExpanded: (expanded: boolean) => void;
|
|
26
13
|
toggleNavigationExpanded: () => void;
|
|
27
14
|
};
|
|
15
|
+
export declare const useMainSectionSidebar: () => {
|
|
16
|
+
mainSectionSidebarVisible: boolean;
|
|
17
|
+
setMainSectionSidebarVisible: (visible: boolean) => void;
|
|
18
|
+
toggleMainSectionSidebarVisible: () => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createFastContext } from '../utils/fast-context.js';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
Provider: PageProvider,
|
|
5
|
+
useStore: usePageStore,
|
|
6
|
+
useStoreSetter: usePageStoreSetter
|
|
7
|
+
} = createFastContext({
|
|
8
|
+
globalHeaderContainer: null,
|
|
9
|
+
mainSectionSidebarVisible: true,
|
|
10
|
+
navigationExpanded: true,
|
|
11
|
+
pageContainer: null
|
|
12
|
+
});
|
|
13
|
+
const usePageNavigation = () => {
|
|
14
|
+
const [navigationExpanded, setPageStore] = usePageStore(store => store.navigationExpanded);
|
|
15
|
+
const setNavigationExpanded = expanded => {
|
|
16
|
+
setPageStore({
|
|
17
|
+
navigationExpanded: expanded
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const toggleNavigationExpanded = () => {
|
|
21
|
+
setPageStore({
|
|
22
|
+
navigationExpanded: !navigationExpanded
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
navigationExpanded,
|
|
27
|
+
setNavigationExpanded,
|
|
28
|
+
toggleNavigationExpanded
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const useMainSectionSidebar = () => {
|
|
32
|
+
const [mainSectionSidebarVisible, setPageStore] = usePageStore(store => store.mainSectionSidebarVisible);
|
|
33
|
+
const setMainSectionSidebarVisible = visible => {
|
|
34
|
+
setPageStore({
|
|
35
|
+
mainSectionSidebarVisible: visible
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const toggleMainSectionSidebarVisible = () => {
|
|
39
|
+
setPageStore({
|
|
40
|
+
mainSectionSidebarVisible: !mainSectionSidebarVisible
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
mainSectionSidebarVisible,
|
|
45
|
+
setMainSectionSidebarVisible,
|
|
46
|
+
toggleMainSectionSidebarVisible
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export { PageProvider, useMainSectionSidebar, usePageNavigation, usePageStore, usePageStoreSetter };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import styles from './page.module.js';
|
|
5
|
+
|
|
6
|
+
const SearchContainer = /*#__PURE__*/forwardRef(({
|
|
7
|
+
className,
|
|
8
|
+
...rest
|
|
9
|
+
}, ref) => {
|
|
10
|
+
return jsx("div", {
|
|
11
|
+
...rest,
|
|
12
|
+
ref: ref,
|
|
13
|
+
className: clsx(styles.searchContainer, className),
|
|
14
|
+
role: "search"
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
SearchContainer.displayName = 'SearchContainer';
|
|
18
|
+
|
|
19
|
+
export { SearchContainer };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import styles from './page.module.js';
|
|
5
|
+
|
|
6
|
+
const SideContentContainer = /*#__PURE__*/forwardRef(({
|
|
7
|
+
className,
|
|
8
|
+
...rest
|
|
9
|
+
}, ref) => {
|
|
10
|
+
return jsx("div", {
|
|
11
|
+
...rest,
|
|
12
|
+
ref: ref,
|
|
13
|
+
className: clsx(styles.sideContentContainer, className)
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
SideContentContainer.displayName = 'SideContentContainer';
|
|
17
|
+
|
|
18
|
+
export { SideContentContainer };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
1
|
+
import { type PageGlobalHeaderProps } from './types';
|
|
2
|
+
export declare const PageGlobalHeaderRoot: import("react").ForwardRefExoticComponent<PageGlobalHeaderProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
3
|
+
export declare const PageGlobalHeader: import("react").ForwardRefExoticComponent<PageGlobalHeaderProps & import("react").RefAttributes<HTMLDivElement>> & {
|
|
4
4
|
/**
|
|
5
5
|
* Container for components related to global search.
|
|
6
6
|
*/
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { useRefWithEffect as useRefWithEffectMemoized } from '../utils/useRefWithEffect.js';
|
|
5
|
+
import { usePageStoreSetter } from './page-context.js';
|
|
6
|
+
import { SearchContainer } from './page-global-header-search-container.js';
|
|
7
|
+
import { SideContentContainer } from './page-global-header-side-content-container.js';
|
|
8
|
+
import styles from './page.module.js';
|
|
9
|
+
|
|
10
|
+
const PageGlobalHeaderRoot = /*#__PURE__*/forwardRef(({
|
|
11
|
+
className,
|
|
12
|
+
...rest
|
|
13
|
+
}, forwardedRef) => {
|
|
14
|
+
const setPageStore = usePageStoreSetter();
|
|
15
|
+
const setRefs = useRefWithEffectMemoized(forwardedRef, node => {
|
|
16
|
+
setPageStore({
|
|
17
|
+
globalHeaderContainer: node
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
return jsx("div", {
|
|
21
|
+
...rest,
|
|
22
|
+
ref: setRefs,
|
|
23
|
+
className: clsx(styles.globalHeader, className),
|
|
24
|
+
role: "banner"
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
PageGlobalHeaderRoot.displayName = 'GlobalHeader';
|
|
28
|
+
const PageGlobalHeader = Object.assign(PageGlobalHeaderRoot, {
|
|
29
|
+
/**
|
|
30
|
+
* Container for components related to global search.
|
|
31
|
+
*/
|
|
32
|
+
SearchContainer,
|
|
33
|
+
/**
|
|
34
|
+
* Container for all components excluding ones related to global search.
|
|
35
|
+
*/
|
|
36
|
+
SideContentContainer
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export { PageGlobalHeader, PageGlobalHeaderRoot };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import styles from './page.module.js';
|
|
5
|
+
|
|
6
|
+
const PageMainSectionContent = /*#__PURE__*/forwardRef(({
|
|
7
|
+
className,
|
|
8
|
+
...rest
|
|
9
|
+
}, forwardedRef) => {
|
|
10
|
+
return jsx("div", {
|
|
11
|
+
...rest,
|
|
12
|
+
ref: forwardedRef,
|
|
13
|
+
className: clsx(styles.content, className)
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export { PageMainSectionContent };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { useBreakpoint, Breakpoint } from '../utils/useBreakpoint.js';
|
|
5
|
+
import { useMainSectionSidebar } from './page-context.js';
|
|
6
|
+
import styles from './page.module.js';
|
|
7
|
+
|
|
8
|
+
const PageMainSectionSidebar = /*#__PURE__*/forwardRef(({
|
|
9
|
+
className,
|
|
10
|
+
...rest
|
|
11
|
+
}, forwardedRef) => {
|
|
12
|
+
const {
|
|
13
|
+
mainSectionSidebarVisible
|
|
14
|
+
} = useMainSectionSidebar();
|
|
15
|
+
const breakpoint = useBreakpoint();
|
|
16
|
+
if (!mainSectionSidebarVisible || breakpoint <= Breakpoint.Medium) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return jsx("div", {
|
|
20
|
+
...rest,
|
|
21
|
+
ref: forwardedRef,
|
|
22
|
+
className: clsx(styles.sidebar, className),
|
|
23
|
+
role: "complementary"
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export { PageMainSectionSidebar };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type PageMainSectionProps } from './types';
|
|
2
|
+
export declare const PageMainSection: import("react").ForwardRefExoticComponent<PageMainSectionProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
3
|
+
export declare const MainSection: import("react").ForwardRefExoticComponent<PageMainSectionProps & import("react").RefAttributes<HTMLDivElement>> & {
|
|
4
|
+
Content: import("react").ForwardRefExoticComponent<import("./types").PageMainProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
5
|
+
Sidebar: import("react").ForwardRefExoticComponent<import("./types").PageMainSectionSidebarProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { PageMainSectionContent } from './page-main-section-content.js';
|
|
5
|
+
import { PageMainSectionSidebar } from './page-main-section-sidebar.js';
|
|
6
|
+
import styles from './page.module.js';
|
|
7
|
+
|
|
8
|
+
const PageMainSection = /*#__PURE__*/forwardRef(({
|
|
9
|
+
className,
|
|
10
|
+
...rest
|
|
11
|
+
}, forwardedRef) => {
|
|
12
|
+
return jsx("div", {
|
|
13
|
+
...rest,
|
|
14
|
+
ref: forwardedRef,
|
|
15
|
+
className: clsx(styles.mainSection, className)
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
const MainSection = Object.assign(PageMainSection, {
|
|
19
|
+
Content: PageMainSectionContent,
|
|
20
|
+
Sidebar: PageMainSectionSidebar
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export { MainSection, PageMainSection };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Portal, FocusTrapRegion } from '@ariakit/react';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { forwardRef, useRef, useCallback } from 'react';
|
|
5
|
+
import { useBreakpoint, Breakpoint } from '../utils/useBreakpoint.js';
|
|
6
|
+
import { usePageStore } from './page-context.js';
|
|
7
|
+
import styles from './page.module.js';
|
|
8
|
+
|
|
9
|
+
const createPortalElementDiv = () => {
|
|
10
|
+
const div = document.createElement('div');
|
|
11
|
+
// Adds className with display:contents property.
|
|
12
|
+
// We want to display only contents of the portal which has position absolute
|
|
13
|
+
// but not the "anchor" which points where the portal should be placed
|
|
14
|
+
div.classList.add(styles.portalEntry);
|
|
15
|
+
return div;
|
|
16
|
+
};
|
|
17
|
+
const PageNavigation = /*#__PURE__*/forwardRef(({
|
|
18
|
+
className,
|
|
19
|
+
children,
|
|
20
|
+
...rest
|
|
21
|
+
}, forwardedRef) => {
|
|
22
|
+
const [{
|
|
23
|
+
navigationExpanded,
|
|
24
|
+
globalHeaderContainer,
|
|
25
|
+
pageContainer
|
|
26
|
+
}] = usePageStore(store => {
|
|
27
|
+
return {
|
|
28
|
+
navigationExpanded: store.navigationExpanded,
|
|
29
|
+
globalHeaderContainer: store.globalHeaderContainer,
|
|
30
|
+
pageContainer: store.pageContainer
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
const breakpoint = useBreakpoint();
|
|
34
|
+
const largeBreakpointActive = breakpoint >= Breakpoint.Large;
|
|
35
|
+
const lessOrEqualMediumBreakpointActive = breakpoint <= Breakpoint.Medium;
|
|
36
|
+
const isFullscreenNavigation = lessOrEqualMediumBreakpointActive && navigationExpanded;
|
|
37
|
+
const portalElement = useRef(null);
|
|
38
|
+
const getPortalElement = useCallback(() => {
|
|
39
|
+
if (!pageContainer || !globalHeaderContainer) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (!portalElement.current) {
|
|
43
|
+
portalElement.current = createPortalElementDiv();
|
|
44
|
+
}
|
|
45
|
+
let portalRoot;
|
|
46
|
+
if (lessOrEqualMediumBreakpointActive) {
|
|
47
|
+
portalRoot = globalHeaderContainer;
|
|
48
|
+
if (pageContainer?.contains(portalElement.current)) {
|
|
49
|
+
pageContainer.removeChild(portalElement.current);
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
portalRoot = pageContainer;
|
|
53
|
+
if (globalHeaderContainer?.contains(portalElement.current)) {
|
|
54
|
+
globalHeaderContainer.removeChild(portalElement.current);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
portalRoot.appendChild(portalElement.current);
|
|
58
|
+
return portalElement.current;
|
|
59
|
+
}, [pageContainer, globalHeaderContainer, lessOrEqualMediumBreakpointActive]);
|
|
60
|
+
return jsx(Portal, {
|
|
61
|
+
...rest,
|
|
62
|
+
className: clsx(styles.navigationPortal, {
|
|
63
|
+
[styles.navigationPortalLargeExpanded]: largeBreakpointActive && navigationExpanded,
|
|
64
|
+
[styles.navigationPortalLargeCollapsed]: largeBreakpointActive && !navigationExpanded,
|
|
65
|
+
[styles.navigationPortalOverlayCollapsed]: lessOrEqualMediumBreakpointActive && !navigationExpanded,
|
|
66
|
+
[styles.navigationPortalOverlayExpanded]: lessOrEqualMediumBreakpointActive && navigationExpanded
|
|
67
|
+
}),
|
|
68
|
+
"data-state": navigationExpanded ? 'expanded' : 'collapsed',
|
|
69
|
+
portalElement: getPortalElement,
|
|
70
|
+
preserveTabOrder: true,
|
|
71
|
+
role: "navigation",
|
|
72
|
+
children: jsx(FocusTrapRegion, {
|
|
73
|
+
ref: forwardedRef,
|
|
74
|
+
className: clsx(styles.navigationContent, className),
|
|
75
|
+
enabled: isFullscreenNavigation,
|
|
76
|
+
children: typeof children === 'function' ? children({
|
|
77
|
+
expanded: Boolean(navigationExpanded)
|
|
78
|
+
}) : children
|
|
79
|
+
})
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
PageNavigation.displayName = 'Navigation';
|
|
83
|
+
|
|
84
|
+
export { PageNavigation };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type PagePageHeaderProps } from './types';
|
|
2
|
+
export declare const PagePageHeader: ((props: PagePageHeaderProps) => import("react/jsx-runtime").JSX.Element) & {
|
|
3
|
+
StartElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
4
|
+
EndElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
5
|
+
Corner: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { PageHeader } from '../primitives/page-header/page-header.js';
|
|
3
|
+
|
|
4
|
+
const PagePageHeaderRoot = props => {
|
|
5
|
+
return jsx(PageHeader.Root, {
|
|
6
|
+
...props,
|
|
7
|
+
as: "div",
|
|
8
|
+
sticky: false,
|
|
9
|
+
variant: "inline"
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
const PagePageHeader = Object.assign(PagePageHeaderRoot, {
|
|
13
|
+
StartElements: PageHeader.StartElements,
|
|
14
|
+
EndElements: PageHeader.EndElements,
|
|
15
|
+
Corner: PageHeader.Corner
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export { PagePageHeader };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare const PageRoot: import("react").ForwardRefExoticComponent<
|
|
1
|
+
import { type PageLayoutProps } from './types';
|
|
2
|
+
export declare const PageRoot: import("react").ForwardRefExoticComponent<PageLayoutProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef, useEffect, Children, isValidElement } from 'react';
|
|
4
|
+
import { useBreakpoint, Breakpoint } from '../utils/useBreakpoint.js';
|
|
5
|
+
import { useRefWithEffect as useRefWithEffectMemoized } from '../utils/useRefWithEffect.js';
|
|
6
|
+
import { PageProvider, usePageStore } from './page-context.js';
|
|
7
|
+
import { PageGlobalHeader } from './page-global-header.js';
|
|
8
|
+
import { MainSection } from './page-main-section.js';
|
|
9
|
+
import { PageNavigation } from './page-navigation.js';
|
|
10
|
+
import { PagePageHeader } from './page-page-header.js';
|
|
11
|
+
import { PageSubNavigation } from './page-subnavigation.js';
|
|
12
|
+
import styles from './page.module.js';
|
|
13
|
+
|
|
14
|
+
const PageRoot = /*#__PURE__*/forwardRef(({
|
|
15
|
+
onToggleNavigationExpanded,
|
|
16
|
+
defaultNavigationExpanded,
|
|
17
|
+
children,
|
|
18
|
+
...rest
|
|
19
|
+
}, forwardedRef) => {
|
|
20
|
+
return jsx(PageProvider, {
|
|
21
|
+
children: jsx(PageLayout, {
|
|
22
|
+
...rest,
|
|
23
|
+
ref: forwardedRef,
|
|
24
|
+
defaultNavigationExpanded: defaultNavigationExpanded,
|
|
25
|
+
onToggleNavigationExpanded: onToggleNavigationExpanded,
|
|
26
|
+
children: children
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
PageRoot.displayName = 'PageRoot';
|
|
31
|
+
const PageLayout = /*#__PURE__*/forwardRef(({
|
|
32
|
+
defaultNavigationExpanded,
|
|
33
|
+
className,
|
|
34
|
+
children,
|
|
35
|
+
...rest
|
|
36
|
+
}, forwardedRef) => {
|
|
37
|
+
const [navigationExpanded, setPageStoreData] = usePageStore(store => store.navigationExpanded);
|
|
38
|
+
const breakpoint = useBreakpoint();
|
|
39
|
+
const xxLargeBreakpointActive = breakpoint === Breakpoint.XXLarge;
|
|
40
|
+
const lessOrEqualMediumBreakpointActive = breakpoint <= Breakpoint.Medium;
|
|
41
|
+
const isFullscreenNavigation = lessOrEqualMediumBreakpointActive && navigationExpanded;
|
|
42
|
+
const setRefs = useRefWithEffectMemoized(forwardedRef, node => setPageStoreData({
|
|
43
|
+
pageContainer: node
|
|
44
|
+
}));
|
|
45
|
+
// this effect has to fire once to set initial state of the navigationExpanded
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setPageStoreData({
|
|
48
|
+
navigationExpanded: defaultNavigationExpanded ?? xxLargeBreakpointActive
|
|
49
|
+
});
|
|
50
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
|
+
}, []);
|
|
52
|
+
const Slots = getChildrenForLandmarks(children);
|
|
53
|
+
return jsxs("div", {
|
|
54
|
+
...rest,
|
|
55
|
+
ref: setRefs,
|
|
56
|
+
className: clsx(styles.page, {
|
|
57
|
+
[styles.pageNavigationXXLargeExpanded]: xxLargeBreakpointActive && navigationExpanded,
|
|
58
|
+
[styles.pageNavigationXXLargeCollapsed]: xxLargeBreakpointActive && !navigationExpanded,
|
|
59
|
+
[styles.pageMediumOrLessViewport]: breakpoint <= Breakpoint.Medium
|
|
60
|
+
}, className),
|
|
61
|
+
children: [Slots.Navigation, Slots.GlobalHeader, jsxs("div", {
|
|
62
|
+
// hide fixed focus trap region problem and overlaying content on the navigation
|
|
63
|
+
className: clsx(styles.pageMain, {
|
|
64
|
+
[styles.hide]: isFullscreenNavigation
|
|
65
|
+
}, className),
|
|
66
|
+
role: "main",
|
|
67
|
+
children: [jsx("div", {
|
|
68
|
+
className: clsx(styles.topSection),
|
|
69
|
+
children: Slots.TopSection
|
|
70
|
+
}), Slots.MainSection]
|
|
71
|
+
})]
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
PageLayout.displayName = 'PageLayout';
|
|
75
|
+
const getChildrenForLandmarks = children => {
|
|
76
|
+
return Children.toArray(children).reduce((acc, child) => {
|
|
77
|
+
if (! /*#__PURE__*/isValidElement(child)) {
|
|
78
|
+
return acc;
|
|
79
|
+
}
|
|
80
|
+
if (child.type === PageNavigation) {
|
|
81
|
+
acc.Navigation = child;
|
|
82
|
+
} else if (child.type === PageGlobalHeader) {
|
|
83
|
+
acc.GlobalHeader = child;
|
|
84
|
+
} else if (child.type === MainSection) {
|
|
85
|
+
acc.MainSection = child;
|
|
86
|
+
} else if (child.type === PagePageHeader) {
|
|
87
|
+
acc.TopSection.unshift(child);
|
|
88
|
+
} else if (child.type === PageSubNavigation) {
|
|
89
|
+
acc.TopSection.push(child);
|
|
90
|
+
}
|
|
91
|
+
return acc;
|
|
92
|
+
}, {
|
|
93
|
+
Navigation: null,
|
|
94
|
+
MainSection: null,
|
|
95
|
+
GlobalHeader: null,
|
|
96
|
+
TopSection: []
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export { PageRoot };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
|
|
4
|
+
const PageSubNavigation = /*#__PURE__*/forwardRef(({
|
|
5
|
+
className,
|
|
6
|
+
...rest
|
|
7
|
+
}, forwardedRef) => {
|
|
8
|
+
return jsx("div", {
|
|
9
|
+
...rest,
|
|
10
|
+
ref: forwardedRef,
|
|
11
|
+
className: className
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export { PageSubNavigation };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import '../index.css';
|
|
2
|
+
var styles = {"page":"bp_page_module_page--47219","globalHeader":"bp_page_module_globalHeader--47219","sideContentContainer":"bp_page_module_sideContentContainer--47219","searchContainer":"bp_page_module_searchContainer--47219","pageMain":"bp_page_module_pageMain--47219","topSection":"bp_page_module_topSection--47219","mainSection":"bp_page_module_mainSection--47219","content":"bp_page_module_content--47219","sidebar":"bp_page_module_sidebar--47219","navigationPortal":"bp_page_module_navigationPortal--47219","navigationContent":"bp_page_module_navigationContent--47219","navigationPortalLargeCollapsed":"bp_page_module_navigationPortalLargeCollapsed--47219","navigationPortalLargeExpanded":"bp_page_module_navigationPortalLargeExpanded--47219","hide":"bp_page_module_hide--47219","pageMediumOrLessViewport":"bp_page_module_pageMediumOrLessViewport--47219","search":"bp_page_module_search--47219","navigationPortalOverlayCollapsed":"bp_page_module_navigationPortalOverlayCollapsed--47219","navigationPortalOverlayExpanded":"bp_page_module_navigationPortalOverlayExpanded--47219","pageNavigationXXLargeCollapsed":"bp_page_module_pageNavigationXXLargeCollapsed--47219","pageNavigationXXLargeExpanded":"bp_page_module_pageNavigationXXLargeExpanded--47219","portalEntry":"bp_page_module_portalEntry--47219"};
|
|
3
|
+
|
|
4
|
+
export { styles as default };
|
package/lib-esm/page/types.d.ts
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
import { type
|
|
3
|
-
export
|
|
4
|
-
export type GlobalHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
5
|
-
export type PageContentProps = React.HTMLAttributes<HTMLDivElement>;
|
|
6
|
-
export interface PageProps extends PageLayoutProps, Pick<PageContextProps, 'onToggleNavigationExpanded'> {
|
|
2
|
+
import { type PageHeaderProps } from '../primitives/page-header';
|
|
3
|
+
export interface PageLayoutProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
7
4
|
/**
|
|
8
|
-
* Whether
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
* - in screens > 1220px the navigation will be initially expanded,
|
|
12
|
-
* - otherwise it will be initially collapsed,
|
|
13
|
-
* */
|
|
5
|
+
* Whether navigation is initially expanded.
|
|
6
|
+
* For viewport greater than 1220px it is expanded by default.
|
|
7
|
+
*/
|
|
14
8
|
defaultNavigationExpanded?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Whether main content sidebar is initially expanded.
|
|
11
|
+
* @default true
|
|
12
|
+
*/
|
|
13
|
+
defaultMainContentSidebarVisible?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Callback called when the navigation is toggled
|
|
16
|
+
*/
|
|
17
|
+
onToggleNavigationExpanded?: (nextState: boolean) => void;
|
|
15
18
|
}
|
|
19
|
+
export type PageGlobalHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
20
|
+
export type PagePageHeaderProps = Omit<PageHeaderProps, 'variant' | 'sticky' | 'as'>;
|
|
21
|
+
export type PageMainProps = React.HTMLAttributes<HTMLDivElement>;
|
|
22
|
+
export type PageMainSectionProps = React.HTMLAttributes<HTMLDivElement>;
|
|
23
|
+
export type PageMainSectionSidebarProps = React.HTMLAttributes<HTMLDivElement>;
|
|
24
|
+
export type PageSubNavigationProps = React.HTMLAttributes<HTMLDivElement>;
|
|
25
|
+
export type PageProps = PageLayoutProps;
|
|
16
26
|
export interface PageNavigationProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
17
27
|
/**
|
|
18
28
|
* The children to render within the navigation
|
|
19
|
-
|
|
29
|
+
*/
|
|
20
30
|
children: ReactNode | (({ expanded }: {
|
|
21
31
|
expanded: boolean;
|
|
22
32
|
}) => ReactNode);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type PageHeaderProps } from './types';
|
|
2
|
-
export declare const PageHeaderRoot: import("react").ForwardRefExoticComponent<
|
|
1
|
+
import { type HeaderElementTypes, type PageHeaderProps } from './types';
|
|
2
|
+
export declare const PageHeaderRoot: import("react").ForwardRefExoticComponent<PageHeaderProps & import("react").RefAttributes<HeaderElementTypes>>;
|
|
3
3
|
export declare const PageHeaderCorner: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const PageHeaderStartElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
5
5
|
export declare const PageHeaderEndElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
6
6
|
export declare const PageHeader: {
|
|
7
|
-
Root: import("react").ForwardRefExoticComponent<
|
|
7
|
+
Root: import("react").ForwardRefExoticComponent<PageHeaderProps & import("react").RefAttributes<HeaderElementTypes>>;
|
|
8
8
|
StartElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
9
9
|
EndElements: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
10
10
|
Corner: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import { forwardRef } from 'react';
|
|
3
|
+
import { forwardRef, createElement } from 'react';
|
|
4
4
|
import styles from './page-header.module.js';
|
|
5
5
|
|
|
6
6
|
const PageHeaderRoot = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
7
7
|
const {
|
|
8
|
+
as = 'header',
|
|
8
9
|
className,
|
|
9
10
|
children,
|
|
10
11
|
variant,
|
|
11
12
|
sticky = true,
|
|
12
13
|
...rest
|
|
13
14
|
} = props;
|
|
14
|
-
return
|
|
15
|
+
return /*#__PURE__*/createElement(as, {
|
|
15
16
|
...rest,
|
|
16
17
|
ref: forwardedRef,
|
|
17
18
|
className: clsx(styles.pageHeader, className, {
|
|
@@ -20,9 +21,8 @@ const PageHeaderRoot = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
20
21
|
[styles.inline]: variant === 'inline'
|
|
21
22
|
}, {
|
|
22
23
|
[styles.sticky]: sticky
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
});
|
|
24
|
+
})
|
|
25
|
+
}, children);
|
|
26
26
|
});
|
|
27
27
|
const PageHeaderCorner = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
28
28
|
const {
|
|
@@ -37,7 +37,7 @@ const PageHeaderCorner = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
37
37
|
children: children
|
|
38
38
|
});
|
|
39
39
|
});
|
|
40
|
-
const
|
|
40
|
+
const PageHeaderStartElements = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
41
41
|
const {
|
|
42
42
|
className,
|
|
43
43
|
children,
|
|
@@ -65,9 +65,9 @@ const PageHeaderEndElements = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
65
65
|
});
|
|
66
66
|
const PageHeader = {
|
|
67
67
|
Root: PageHeaderRoot,
|
|
68
|
-
StartElements:
|
|
68
|
+
StartElements: PageHeaderStartElements,
|
|
69
69
|
EndElements: PageHeaderEndElements,
|
|
70
70
|
Corner: PageHeaderCorner
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
-
export {
|
|
73
|
+
export { PageHeader, PageHeaderCorner, PageHeaderEndElements, PageHeaderRoot, PageHeaderStartElements };
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type HTMLAttributes } from 'react';
|
|
2
|
+
interface HeaderProps extends HTMLAttributes<HTMLElement> {
|
|
3
|
+
as?: 'header';
|
|
4
|
+
}
|
|
5
|
+
interface DivProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
as: 'div';
|
|
7
|
+
}
|
|
8
|
+
export type HeaderElementTypes = HeaderProps | DivProps;
|
|
9
|
+
export type PageHeaderProps = (DivProps | HeaderProps) & {
|
|
3
10
|
variant: 'default' | 'inline';
|
|
4
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* When true the header will have `position: sticky`
|
|
5
13
|
* @default true
|
|
6
14
|
*/
|
|
7
15
|
sticky?: boolean;
|
|
8
|
-
}
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare function createFastContext<Store>(initialState: Store): {
|
|
3
|
+
Provider: ({ children }: {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
useStore: <SelectorOutput>(selector: (store: Store) => SelectorOutput) => [SelectorOutput, (value: Partial<Store>) => void];
|
|
7
|
+
useStoreSetter: () => (value: Partial<Store>) => void;
|
|
8
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useContext, useState, useEffect, useRef, useCallback, createContext } from 'react';
|
|
3
|
+
|
|
4
|
+
function createFastContext(initialState) {
|
|
5
|
+
function useStoreData() {
|
|
6
|
+
const store = useRef(initialState);
|
|
7
|
+
const get = useCallback(() => store.current, []);
|
|
8
|
+
const subscribers = useRef(new Set());
|
|
9
|
+
const set = useCallback(value => {
|
|
10
|
+
store.current = {
|
|
11
|
+
...store.current,
|
|
12
|
+
...value
|
|
13
|
+
};
|
|
14
|
+
subscribers.current.forEach(callback => callback());
|
|
15
|
+
}, []);
|
|
16
|
+
const subscribe = useCallback(callback => {
|
|
17
|
+
subscribers.current.add(callback);
|
|
18
|
+
return () => subscribers.current.delete(callback);
|
|
19
|
+
}, []);
|
|
20
|
+
return {
|
|
21
|
+
get,
|
|
22
|
+
set,
|
|
23
|
+
subscribe
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const StoreContext = /*#__PURE__*/createContext(null);
|
|
27
|
+
function Provider({
|
|
28
|
+
children
|
|
29
|
+
}) {
|
|
30
|
+
return jsx(StoreContext.Provider, {
|
|
31
|
+
value: useStoreData(),
|
|
32
|
+
children: children
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function useStore(selector) {
|
|
36
|
+
const store = useContext(StoreContext);
|
|
37
|
+
if (!store) {
|
|
38
|
+
throw new Error('Store not found');
|
|
39
|
+
}
|
|
40
|
+
const [state, setState] = useState(() => selector(store.get() || initialState));
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
return store.subscribe(() => {
|
|
43
|
+
setState(selector(store.get()));
|
|
44
|
+
});
|
|
45
|
+
}, [selector, store]);
|
|
46
|
+
// This is an alternative implementation of above code using useSyncExternalStore - requires react 18
|
|
47
|
+
// const state = useSyncExternalStore(
|
|
48
|
+
// store.subscribe,
|
|
49
|
+
// () => selector(store.get()),
|
|
50
|
+
// () => selector(initialState),
|
|
51
|
+
// );
|
|
52
|
+
return [state, store.set];
|
|
53
|
+
}
|
|
54
|
+
function useStoreSetter() {
|
|
55
|
+
const store = useContext(StoreContext);
|
|
56
|
+
if (!store) {
|
|
57
|
+
throw new Error('Store not found');
|
|
58
|
+
}
|
|
59
|
+
return store.set;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
Provider,
|
|
63
|
+
useStore,
|
|
64
|
+
useStoreSetter
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { createFastContext };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ForwardedRef, type RefCallback } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Returns memoized function that sets ref with side effect.
|
|
4
|
+
*/
|
|
5
|
+
declare function useRefWithEffectMemoized<T>(forwardedRef: ForwardedRef<T>, callback?: RefCallback<T>): (node: T | null) => void;
|
|
6
|
+
export { useRefWithEffectMemoized as useRefWithEffect };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns function that sets ref and invokes provided ref callback function.
|
|
5
|
+
*/
|
|
6
|
+
function createSetRefWithEffect(forwardedRef, callback) {
|
|
7
|
+
return node => {
|
|
8
|
+
if (callback) {
|
|
9
|
+
callback(node);
|
|
10
|
+
}
|
|
11
|
+
if (typeof forwardedRef === 'function') {
|
|
12
|
+
forwardedRef(node);
|
|
13
|
+
} else if (forwardedRef) {
|
|
14
|
+
forwardedRef.current = node;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns memoized function that sets ref with side effect.
|
|
20
|
+
*/
|
|
21
|
+
function useRefWithEffectMemoized(forwardedRef, callback) {
|
|
22
|
+
return useMemo(() => createSetRefWithEffect(forwardedRef, callback), [forwardedRef, callback]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { useRefWithEffectMemoized as useRefWithEffect };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@box/blueprint-web",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"**/*.scss"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@ariakit/react": "0.4.
|
|
26
|
-
"@ariakit/react-core": "0.4.
|
|
25
|
+
"@ariakit/react": "0.4.14",
|
|
26
|
+
"@ariakit/react-core": "0.4.14",
|
|
27
27
|
"@box/blueprint-web-assets": "^4.30.0",
|
|
28
28
|
"@internationalized/date": "^3.5.4",
|
|
29
29
|
"@radix-ui/react-accordion": "1.1.2",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"react-stately": "^3.31.1",
|
|
64
64
|
"tsx": "^4.16.5"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "8371b326ea09e2a07955fb57e63e15e9b14abc4c",
|
|
67
67
|
"module": "lib-esm/index.js",
|
|
68
68
|
"main": "lib-esm/index.js",
|
|
69
69
|
"exports": {
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type ForwardedRef, type RefCallback } from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* Returns function that sets ref and invokes provided ref callback function.
|
|
4
|
-
*/
|
|
5
|
-
export declare function createSetRefWithCallback<T>(forwardedRef: ForwardedRef<T>, callback?: RefCallback<T>): (node: T | null) => void;
|
|
6
|
-
/**
|
|
7
|
-
* Memoized version of createSetRefWithCallback.
|
|
8
|
-
* Returns function that sets ref and invokes provided ref callback function.
|
|
9
|
-
*/
|
|
10
|
-
export declare function useCreateSetRefWithCallbackMemo<T>(forwardedRef: ForwardedRef<T>, callback?: RefCallback<T>): (node: T | null) => void;
|