@k2b/ui 0.22.0 → 0.23.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.
Files changed (98) hide show
  1. package/dist/browser/content/Calendar.js +1086 -1049
  2. package/dist/browser/content/Calendar.js.map +1 -1
  3. package/dist/browser/content/CalendarDayView.js +1187 -0
  4. package/dist/browser/content/CalendarDayView.js.map +1 -0
  5. package/dist/browser/content/CalendarWeekView.js +1571 -0
  6. package/dist/browser/content/CalendarWeekView.js.map +1 -0
  7. package/dist/browser/content/ChartExplorer.js +174 -82
  8. package/dist/browser/content/ChartExplorer.js.map +1 -1
  9. package/dist/browser/content/ChartFilterControls.js +90 -33
  10. package/dist/browser/content/ChartFilterControls.js.map +1 -1
  11. package/dist/browser/content/DataTable.js +199 -171
  12. package/dist/browser/content/DataTable.js.map +1 -1
  13. package/dist/browser/content/calendar-day-scroll.js +98 -0
  14. package/dist/browser/content/calendar-day-scroll.js.map +1 -0
  15. package/dist/browser/content/calendar-days.js +408 -0
  16. package/dist/browser/content/calendar-days.js.map +1 -0
  17. package/dist/browser/content/calendar-dialogs.js +236 -0
  18. package/dist/browser/content/calendar-dialogs.js.map +1 -0
  19. package/dist/browser/content/calendar-messages.js +210 -2
  20. package/dist/browser/content/calendar-messages.js.map +1 -1
  21. package/dist/browser/content/calendar-pointer.js +15 -3
  22. package/dist/browser/content/calendar-pointer.js.map +1 -1
  23. package/dist/browser/content/calendar-shared.js +328 -0
  24. package/dist/browser/content/calendar-shared.js.map +1 -0
  25. package/dist/browser/content/calendar-time-view.js +1649 -0
  26. package/dist/browser/content/calendar-time-view.js.map +1 -0
  27. package/dist/browser/content/chart-messages.js +10 -0
  28. package/dist/browser/content/chart-messages.js.map +1 -1
  29. package/dist/browser/content/index.js.map +1 -1
  30. package/dist/browser/inputs/Combobox.js +0 -1
  31. package/dist/browser/inputs/Combobox.js.map +1 -1
  32. package/dist/browser/layout/AppWorkspace.js +123 -97
  33. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  34. package/dist/browser/layout/PageTitle.js +4 -1
  35. package/dist/browser/layout/PageTitle.js.map +1 -1
  36. package/dist/browser/layout/app-workspace-controller.js +164 -86
  37. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  38. package/dist/browser/surfaces/StatCell.js +18 -6
  39. package/dist/browser/surfaces/StatCell.js.map +1 -1
  40. package/dist/ssr/content/Calendar.js +524 -335
  41. package/dist/ssr/content/Calendar.js.map +1 -1
  42. package/dist/ssr/content/CalendarDayView.js +800 -0
  43. package/dist/ssr/content/CalendarDayView.js.map +1 -0
  44. package/dist/ssr/content/CalendarWeekView.js +1069 -0
  45. package/dist/ssr/content/CalendarWeekView.js.map +1 -0
  46. package/dist/ssr/content/ChartExplorer.js +93 -34
  47. package/dist/ssr/content/ChartExplorer.js.map +1 -1
  48. package/dist/ssr/content/ChartFilterControls.js +49 -7
  49. package/dist/ssr/content/ChartFilterControls.js.map +1 -1
  50. package/dist/ssr/content/DataTable.js +69 -51
  51. package/dist/ssr/content/DataTable.js.map +1 -1
  52. package/dist/ssr/content/calendar-day-scroll.js +98 -0
  53. package/dist/ssr/content/calendar-day-scroll.js.map +1 -0
  54. package/dist/ssr/content/calendar-days.js +408 -0
  55. package/dist/ssr/content/calendar-days.js.map +1 -0
  56. package/dist/ssr/content/calendar-dialogs.js +159 -0
  57. package/dist/ssr/content/calendar-dialogs.js.map +1 -0
  58. package/dist/ssr/content/calendar-messages.js +210 -2
  59. package/dist/ssr/content/calendar-messages.js.map +1 -1
  60. package/dist/ssr/content/calendar-pointer.js +15 -3
  61. package/dist/ssr/content/calendar-pointer.js.map +1 -1
  62. package/dist/ssr/content/calendar-shared.js +261 -0
  63. package/dist/ssr/content/calendar-shared.js.map +1 -0
  64. package/dist/ssr/content/calendar-time-view.js +1306 -0
  65. package/dist/ssr/content/calendar-time-view.js.map +1 -0
  66. package/dist/ssr/content/chart-messages.js +10 -0
  67. package/dist/ssr/content/chart-messages.js.map +1 -1
  68. package/dist/ssr/content/index.js.map +1 -1
  69. package/dist/ssr/inputs/Combobox.js.map +1 -1
  70. package/dist/ssr/layout/AppWorkspace.js +38 -29
  71. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  72. package/dist/ssr/layout/PageTitle.js +4 -1
  73. package/dist/ssr/layout/PageTitle.js.map +1 -1
  74. package/dist/ssr/layout/app-workspace-controller.js +164 -86
  75. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  76. package/dist/ssr/surfaces/StatCell.js +2 -2
  77. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  78. package/dist/styles.css +1 -1
  79. package/dist/types/content/Calendar.d.ts +91 -0
  80. package/dist/types/content/CalendarDayView.d.ts +7 -0
  81. package/dist/types/content/CalendarWeekView.d.ts +7 -0
  82. package/dist/types/content/ChartExplorer.d.ts +36 -1
  83. package/dist/types/content/ChartFilterControls.d.ts +6 -1
  84. package/dist/types/content/DataTable.d.ts +5 -0
  85. package/dist/types/content/calendar-day-scroll.d.ts +42 -0
  86. package/dist/types/content/calendar-days.d.ts +192 -0
  87. package/dist/types/content/calendar-dialogs.d.ts +22 -0
  88. package/dist/types/content/calendar-messages.d.ts +99 -0
  89. package/dist/types/content/calendar-pointer.d.ts +9 -0
  90. package/dist/types/content/calendar-shared.d.ts +69 -0
  91. package/dist/types/content/calendar-time-view.d.ts +252 -0
  92. package/dist/types/content/chart-messages.d.ts +5 -0
  93. package/dist/types/content/index.d.ts +2 -2
  94. package/dist/types/layout/AppWorkspace.d.ts +25 -3
  95. package/dist/types/layout/PageTitle.d.ts +2 -1
  96. package/dist/types/layout/app-workspace-controller.d.ts +9 -1
  97. package/dist/types/surfaces/StatCell.d.ts +5 -0
  98. package/package.json +1 -1
@@ -49,10 +49,12 @@ var _tmpl$ = ["<button type=\"button\" class=\"k2b-app-workspace__resize\" role=
49
49
  _tmpl$38 = ["<i", " aria-hidden=\"true\"></i>"],
50
50
  _tmpl$39 = "<i class=\"ti ti-layout-sidebar\" aria-hidden=\"true\"></i>",
51
51
  _tmpl$40 = ["<div class=\"k2b-app-workspace__head\"", ">", "", "</div>"],
52
- _tmpl$41 = ["<div class=\"", "\" data-k2b-app-workspace", " style=\"", "\">", "", "</div>"],
53
- _tmpl$42 = ["<div class=\"", "\">", "</div>"];
52
+ _tmpl$41 = ["<h1 class=\"k2b-app-workspace__head-heading\" data-k2b-page-trail-title", ">", "</h1>"],
53
+ _tmpl$42 = ["<div class=\"", "\" data-k2b-app-workspace", " style=\"", "\">", "", "</div>"],
54
+ _tmpl$43 = ["<div class=\"", "\">", "</div>"];
54
55
  import { Link } from "@k2b/ssr/nav";
55
56
  import { children, createContext, createEffect, createMemo, createSignal, createUniqueId, For, mergeProps, onCleanup, onMount, Show, useContext } from "solid-js";
57
+ import { isServer } from "solid-js/web";
56
58
  import { IconButton } from "../actions/Button";
57
59
  import { APP_WORKSPACE_DETAIL_CLOSE_EVENT, APP_WORKSPACE_DETAIL_STEP_EVENT, APP_WORKSPACE_SIDEBAR_HIDE_EVENT, installAppWorkspaceController } from "./app-workspace-controller";
58
60
  import { APP_WORKSPACE_DETAIL_DEFAULT, APP_WORKSPACE_DETAIL_MAX, APP_WORKSPACE_DETAIL_MIN, APP_WORKSPACE_DRAWER_DEFAULT, APP_WORKSPACE_DRAWER_MAX, APP_WORKSPACE_DRAWER_MIN, APP_WORKSPACE_PANE_DEFAULT, APP_WORKSPACE_PANE_MAX, APP_WORKSPACE_PANE_MIN, APP_WORKSPACE_SIDEBAR_COLLAPSED, APP_WORKSPACE_SIDEBAR_DEFAULT, APP_WORKSPACE_SIDEBAR_MAX, APP_WORKSPACE_SIDEBAR_MIN, appWorkspaceLayoutStyle, appWorkspacePanelVariable } from "./app-workspace-state";
@@ -286,20 +288,22 @@ function AppWorkspaceDetail(props) {
286
288
  "--k2b-workspace-panel-min": `${minWidth()}px`,
287
289
  "--k2b-workspace-panel-max": `${maxWidth()}px`
288
290
  });
289
- // The panel floats over the content area, and `Main` beside it makes room
290
- // in CSS alone, so a server-rendered page arrives in its final geometry. A
291
- // sibling cannot read the panel's own variables, so this rule hands the
292
- // open panel's size to the content area around it.
293
- const contentRule = () => {
291
+ // An open panel takes a column at the workspace's end, sized in CSS alone,
292
+ // so a server-rendered page arrives in its final geometry. The workspace
293
+ // cannot read the panel's own variables, so this rule hands the open
294
+ // panel's size to its workspace.
295
+ const workspaceRule = () => {
294
296
  const open = `#${domId()}:not([hidden])`;
295
- return `.k2b-app-workspace__content:has(> ${open}, > :is(solid-island, solid-client) > ${open}){--k2b-detail-size:${size()};--k2b-detail-min:${minWidth()}px;--k2b-detail-max:${maxWidth()}px}`;
297
+ return `.k2b-app-workspace:has(> .k2b-app-workspace__content > ${open}, > .k2b-app-workspace__content > :is(solid-island, solid-client) > ${open}){--k2b-detail-size:${size()};--k2b-detail-min:${minWidth()}px;--k2b-detail-max:${maxWidth()}px}`;
296
298
  };
297
299
  let aside;
298
300
  onMount(() => {
299
301
  const close = () => props.onClose?.();
302
+ const isStep = detail => typeof detail === "object" && detail !== null && "direction" in detail && (detail.direction === 1 || detail.direction === -1);
300
303
  const step = event => {
301
- const direction = event instanceof CustomEvent ? event.detail?.direction : undefined;
302
- if (direction === 1 || direction === -1) props.onStep?.(direction);
304
+ if (!(event instanceof CustomEvent) || !isStep(event.detail)) return;
305
+ const item = props.onStep?.(event.detail.direction);
306
+ if (item instanceof HTMLElement) event.detail.item = item;
303
307
  };
304
308
  aside?.addEventListener(APP_WORKSPACE_DETAIL_CLOSE_EVENT, close);
305
309
  aside?.addEventListener(APP_WORKSPACE_DETAIL_STEP_EVENT, step);
@@ -308,7 +312,7 @@ function AppWorkspaceDetail(props) {
308
312
  aside?.removeEventListener(APP_WORKSPACE_DETAIL_STEP_EVENT, step);
309
313
  });
310
314
  });
311
- return [_$ssr(_tmpl$4, contentRule()), _$createComponent(Show, {
315
+ return [_$ssr(_tmpl$4, workspaceRule()), _$createComponent(Show, {
312
316
  get when() {
313
317
  return resizable();
314
318
  },
@@ -455,11 +459,12 @@ const AppWorkspaceSidebarDesktop = props => ({
455
459
  // hydrates. Islands load asynchronously and server-only sidebars never mount,
456
460
  // so `onMount` would be too late or never run. The memory is one
457
461
  // `sessionStorage` entry per path segment and sidebar position and ends with
458
- // the tab. A stored offset is applied first; the current item is then kept in
459
- // view, which is a no-op when the offset already shows it. The frame callback
462
+ // the tab. A stored offset is applied first; the current item, or on a deeper
463
+ // page the item that contains it, is then kept in view, which is a no-op when
464
+ // the offset already shows it. The frame callback
460
465
  // repeats the restore once the whole document is parsed, because content that
461
466
  // follows the sidebar can still change its height before the first paint.
462
- const SIDEBAR_SCROLL_MEMORY_SCRIPT = ["(function(){", "var body=document.currentScript&&document.currentScript.previousElementSibling;if(!body)return;", "var storage;try{storage=window.sessionStorage}catch(_){return}", 'var key="k2b-sidebar-scroll:"+location.pathname.split("/")[1]+":"+document.querySelectorAll(".k2b-app-workspace__sidebar-body").length;', "var restore=function(){", "var stored=storage.getItem(key);if(stored!==null)body.scrollTop=Number(stored);", 'var current=body.querySelector(\'[aria-current="page"]\');if(current)current.scrollIntoView({block:"nearest"});', "};", "restore();requestAnimationFrame(restore);", "var frame=0;", 'body.addEventListener("scroll",function(){if(frame)return;frame=requestAnimationFrame(function(){frame=0;try{storage.setItem(key,String(body.scrollTop))}catch(_){}})},{passive:true});', "})();"].join("");
467
+ const SIDEBAR_SCROLL_MEMORY_SCRIPT = ["(function(){", "var body=document.currentScript&&document.currentScript.previousElementSibling;if(!body)return;", "var storage;try{storage=window.sessionStorage}catch(_){return}", 'var key="k2b-sidebar-scroll:"+location.pathname.split("/")[1]+":"+document.querySelectorAll(".k2b-app-workspace__sidebar-body").length;', "var restore=function(){", "var stored=storage.getItem(key);if(stored!==null)body.scrollTop=Number(stored);", 'var current=body.querySelector(\'[aria-current="page"]\')||body.querySelector(\'[aria-current="true"]\');if(current)current.scrollIntoView({block:"nearest"});', "};", "restore();requestAnimationFrame(restore);", "var frame=0;", 'body.addEventListener("scroll",function(){if(frame)return;frame=requestAnimationFrame(function(){frame=0;try{storage.setItem(key,String(body.scrollTop))}catch(_){}})},{passive:true});', "})();"].join("");
463
468
  const AppWorkspaceSidebarBody = props => {
464
469
  let body;
465
470
  createScrollFade(() => body, () => props.scrollFade !== false);
@@ -551,11 +556,12 @@ const AppWorkspaceSidebarItemAction = props => mergeProps({
551
556
  const AppWorkspaceSidebarItemActions = props => _$ssr(_tmpl$15, _$ssrAttribute("data-visibility", props.visibility === "hover" ? "hover" : _$escape(undefined, true), false), _$escape(props.children));
552
557
  const AppWorkspaceSidebarItemStatus = props => {
553
558
  const workspaceMessages = useWorkspaceMessages();
554
- const count = () => typeof props.unread === "number" && props.unread >= 1 ? Math.floor(props.unread) : 0;
555
- const dot = () => props.unread === true;
559
+ const waiting = () => props.waiting && Number.isFinite(props.waiting.count) ? Math.max(0, Math.floor(props.waiting.count)) : null;
560
+ const count = () => waiting() ?? (typeof props.unread === "number" && props.unread >= 1 ? Math.floor(props.unread) : 0);
561
+ const dot = () => waiting() === null && props.unread === true;
556
562
  // The marks are decorative; the row's accessible name gets one phrase instead,
557
563
  // which says no more than the "99+" a capped count shows.
558
- const description = () => [count() > 99 ? workspaceMessages().sidebarUnreadMany : count() ? workspaceMessages().sidebarUnread({
564
+ const description = () => [waiting() !== null ? props.waiting?.label ?? "" : count() > 99 ? workspaceMessages().sidebarUnreadMany : count() ? workspaceMessages().sidebarUnread({
559
565
  count: count()
560
566
  }) : dot() ? workspaceMessages().sidebarNewActivity : "", props.mention ? workspaceMessages().sidebarMentioned : "", props.muted ? workspaceMessages().sidebarMuted : ""].filter(Boolean).join(", ");
561
567
  // The unread slot stays reserved at the end, and the marks that change most
@@ -565,7 +571,7 @@ const AppWorkspaceSidebarItemStatus = props => {
565
571
  return description();
566
572
  },
567
573
  get children() {
568
- return _$ssr(_tmpl$19, _$ssrAttribute("data-unread", count() ? "count" : dot() ? "dot" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
574
+ return _$ssr(_tmpl$19, _$ssrAttribute("data-unread", waiting() !== null ? _$escape(undefined, true) : count() ? "count" : dot() ? "dot" : _$escape(undefined, true), false) + _$ssrAttribute("data-waiting", waiting() === null ? _$escape(undefined, true) : waiting() ? "count" : "zero", false), _$escape(_$createComponent(Show, {
569
575
  get when() {
570
576
  return props.mention;
571
577
  },
@@ -581,7 +587,7 @@ const AppWorkspaceSidebarItemStatus = props => {
581
587
  }
582
588
  })), _$escape(_$createComponent(Show, {
583
589
  get when() {
584
- return count();
590
+ return count() || waiting() === 0;
585
591
  },
586
592
  get fallback() {
587
593
  return _$createComponent(Show, {
@@ -614,7 +620,7 @@ function AppWorkspaceSidebarRow(props) {
614
620
  },
615
621
  ...data()
616
622
  });
617
- const current = () => props.active ? "page" : undefined;
623
+ const current = () => props.active === "ancestor" ? "true" : props.active ? "page" : undefined;
618
624
  const Control = control => {
619
625
  const attrs = () => control.grouped ? {
620
626
  class: "k2b-app-workspace__sidebar-item-main"
@@ -1318,11 +1324,14 @@ const AppWorkspaceSidebarIconAction = props => {
1318
1324
  };
1319
1325
  /**
1320
1326
  * The row above the work area. From 48 to 64 rem it holds the button that
1321
- * opens the overlay sidebar. On a page with a page above it, at every width,
1322
- * it shows the host's page title with the way up (see `PageTitle`); the
1323
- * page's own `PageTitle` takes its place. It is one fixed height and draws no
1324
- * line; CSS decides when it shows, so the server-rendered page already has
1325
- * its final geometry.
1327
+ * opens the overlay sidebar. On a page with a page above it, it shows the
1328
+ * host's page title with the way up (see `PageTitle`); the page's own
1329
+ * `PageTitle` takes its place. The visible title is no heading, because many
1330
+ * pages render their own `h1`. From 64 rem a sidebar that marks the current
1331
+ * page names it already: the row hides, and only on a page without its own
1332
+ * `h1` its heading stays for assistive technology. It is one fixed height
1333
+ * and draws no line; CSS decides when it shows, so the server-rendered page
1334
+ * already has its final geometry.
1326
1335
  */
1327
1336
  function AppWorkspaceHead(props) {
1328
1337
  const messages = useWorkspaceMessages();
@@ -1345,13 +1354,13 @@ function AppWorkspaceHead(props) {
1345
1354
  get when() {
1346
1355
  return trail();
1347
1356
  },
1348
- children: current => _$createComponent(PageTitle, {
1357
+ children: current => [_$createComponent(PageTitle, {
1349
1358
  get trail() {
1350
1359
  return current();
1351
1360
  },
1352
1361
  as: "p",
1353
1362
  fallback: true
1354
- })
1363
+ }), _$ssr(_tmpl$41, _$ssrAttribute("data-k2b-server", isServer ? "" : _$escape(undefined, true), false), _$escape(current().title))]
1355
1364
  })));
1356
1365
  }
1357
1366
  const AppWorkspace = props => {
@@ -1386,7 +1395,7 @@ const AppWorkspace = props => {
1386
1395
  return _$createComponent(WorkspaceContext.Provider, {
1387
1396
  value: workspace,
1388
1397
  get children() {
1389
- return _$ssr(_tmpl$41, `k2b-app-workspace ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("data-mobile-surface", _$escape(props.mobileSurface, true), false) + _$ssrAttribute("data-sidebar-collapsed", initialLayoutState()?.sidebarCollapsed === undefined ? _$escape(undefined, true) : _$escape(String(initialLayoutState()?.sidebarCollapsed), true), false) + _$ssrAttribute("data-workspace-resizable", props.resizable === false ? "false" : "true", false), _$ssrStyle(appWorkspaceLayoutStyle(initialLayoutState())), _$escape(_$createComponent(AppWorkspaceHead, {
1398
+ return _$ssr(_tmpl$42, `k2b-app-workspace ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("data-mobile-surface", _$escape(props.mobileSurface, true), false) + _$ssrAttribute("data-flat", props.flat ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-sidebar-collapsed", initialLayoutState()?.sidebarCollapsed === undefined ? _$escape(undefined, true) : _$escape(String(initialLayoutState()?.sidebarCollapsed), true), false) + _$ssrAttribute("data-workspace-resizable", props.resizable === false ? "false" : "true", false), _$ssrStyle(appWorkspaceLayoutStyle(initialLayoutState())), _$escape(_$createComponent(AppWorkspaceHead, {
1390
1399
  sidebarId: sidebarId,
1391
1400
  nested: nested
1392
1401
  })), _$escape(props.children));
@@ -1403,7 +1412,7 @@ AppWorkspace.LayoutStateProvider = props => _$createComponent(LayoutStateContext
1403
1412
  return props.children;
1404
1413
  }
1405
1414
  });
1406
- AppWorkspace.Content = props => _$ssr(_tmpl$42, `k2b-app-workspace__content ${_$escape(props.class ?? "", true)}`, _$escape(props.children));
1415
+ AppWorkspace.Content = props => _$ssr(_tmpl$43, `k2b-app-workspace__content ${_$escape(props.class ?? "", true)}`, _$escape(props.children));
1407
1416
  AppWorkspace.Main = AppWorkspaceMain;
1408
1417
  AppWorkspace.MainPane = AppWorkspaceMainPane;
1409
1418
  AppWorkspace.Detail = AppWorkspaceDetail;