@panneau/app 5.0.0-alpha.4 → 5.0.0-alpha.5

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 (103) hide show
  1. package/README.md +32 -5
  2. package/dist/Panneau.css +19 -0
  3. package/dist/Panneau.d.ts +7 -1
  4. package/dist/Panneau.d.ts.map +1 -1
  5. package/dist/Panneau.js +137 -30
  6. package/dist/Panneau.js.map +1 -1
  7. package/dist/Panneau.module.js +12 -0
  8. package/dist/Panneau.module.js.map +1 -0
  9. package/dist/Shell.d.ts +8 -3
  10. package/dist/Shell.d.ts.map +1 -1
  11. package/dist/Shell.js +272 -114
  12. package/dist/Shell.js.map +1 -1
  13. package/dist/createPanneauApp.d.ts +3 -0
  14. package/dist/createPanneauApp.d.ts.map +1 -1
  15. package/dist/createPanneauApp.js.map +1 -1
  16. package/dist/cx.d.ts +3 -0
  17. package/dist/cx.d.ts.map +1 -0
  18. package/dist/cx.js +9 -0
  19. package/dist/cx.js.map +1 -0
  20. package/dist/documentTitle.d.ts +10 -0
  21. package/dist/documentTitle.d.ts.map +1 -0
  22. package/dist/documentTitle.js +49 -0
  23. package/dist/documentTitle.js.map +1 -0
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -1
  27. package/dist/location.d.ts +13 -1
  28. package/dist/location.d.ts.map +1 -1
  29. package/dist/location.js +55 -48
  30. package/dist/location.js.map +1 -1
  31. package/dist/navigation.d.ts +53 -0
  32. package/dist/navigation.d.ts.map +1 -0
  33. package/dist/navigation.js +117 -0
  34. package/dist/navigation.js.map +1 -0
  35. package/dist/pages/HomePage.d.ts +11 -0
  36. package/dist/pages/HomePage.d.ts.map +1 -0
  37. package/dist/pages/HomePage.js +111 -0
  38. package/dist/pages/HomePage.js.map +1 -0
  39. package/dist/pages/ItemPanel.css +164 -0
  40. package/dist/pages/ItemPanel.d.ts +17 -0
  41. package/dist/pages/ItemPanel.d.ts.map +1 -0
  42. package/dist/pages/ItemPanel.js +370 -0
  43. package/dist/pages/ItemPanel.js.map +1 -0
  44. package/dist/pages/ItemPanel.module.js +34 -0
  45. package/dist/pages/ItemPanel.module.js.map +1 -0
  46. package/dist/pages/ItemPreview.d.ts +15 -0
  47. package/dist/pages/ItemPreview.d.ts.map +1 -0
  48. package/dist/pages/ItemPreview.js +179 -0
  49. package/dist/pages/ItemPreview.js.map +1 -0
  50. package/dist/pages/NotFoundPage.d.ts +6 -0
  51. package/dist/pages/NotFoundPage.d.ts.map +1 -0
  52. package/dist/pages/NotFoundPage.js +93 -0
  53. package/dist/pages/NotFoundPage.js.map +1 -0
  54. package/dist/pages/PageHeader.d.ts +21 -0
  55. package/dist/pages/PageHeader.d.ts.map +1 -0
  56. package/dist/pages/PageHeader.js +86 -0
  57. package/dist/pages/PageHeader.js.map +1 -0
  58. package/dist/pages/ResourceFormPage.d.ts +15 -0
  59. package/dist/pages/ResourceFormPage.d.ts.map +1 -0
  60. package/dist/pages/ResourceFormPage.js +204 -0
  61. package/dist/pages/ResourceFormPage.js.map +1 -0
  62. package/dist/pages/ResourceListPage.d.ts +15 -0
  63. package/dist/pages/ResourceListPage.d.ts.map +1 -0
  64. package/dist/pages/ResourceListPage.js +101 -0
  65. package/dist/pages/ResourceListPage.js.map +1 -0
  66. package/dist/pages/itemTitle.d.ts +7 -0
  67. package/dist/pages/itemTitle.d.ts.map +1 -0
  68. package/dist/pages/itemTitle.js +18 -0
  69. package/dist/pages/itemTitle.js.map +1 -0
  70. package/dist/pages/pages.css +162 -0
  71. package/dist/pages/pages.module.js +40 -0
  72. package/dist/pages/pages.module.js.map +1 -0
  73. package/dist/preferences.d.ts +6 -0
  74. package/dist/preferences.d.ts.map +1 -0
  75. package/dist/preferences.js +53 -0
  76. package/dist/preferences.js.map +1 -0
  77. package/dist/recentItems.d.ts +15 -0
  78. package/dist/recentItems.d.ts.map +1 -0
  79. package/dist/recentItems.js +70 -0
  80. package/dist/recentItems.js.map +1 -0
  81. package/dist/shell/AppLayout.css +189 -0
  82. package/dist/shell/AppLayout.d.ts +22 -0
  83. package/dist/shell/AppLayout.d.ts.map +1 -0
  84. package/dist/shell/AppLayout.js +365 -0
  85. package/dist/shell/AppLayout.js.map +1 -0
  86. package/dist/shell/AppLayout.module.js +36 -0
  87. package/dist/shell/AppLayout.module.js.map +1 -0
  88. package/dist/shell/GoTo.d.ts +20 -0
  89. package/dist/shell/GoTo.d.ts.map +1 -0
  90. package/dist/shell/GoTo.js +370 -0
  91. package/dist/shell/GoTo.js.map +1 -0
  92. package/dist/shell/Sidebar.css +313 -0
  93. package/dist/shell/Sidebar.d.ts +29 -0
  94. package/dist/shell/Sidebar.d.ts.map +1 -0
  95. package/dist/shell/Sidebar.js +225 -0
  96. package/dist/shell/Sidebar.js.map +1 -0
  97. package/dist/shell/Sidebar.module.js +60 -0
  98. package/dist/shell/Sidebar.module.js.map +1 -0
  99. package/dist/shell/tokens.d.ts +23 -0
  100. package/dist/shell/tokens.d.ts.map +1 -0
  101. package/dist/shell/tokens.js +75 -0
  102. package/dist/shell/tokens.js.map +1 -0
  103. package/package.json +15 -6
@@ -0,0 +1,93 @@
1
+ import { useDocumentTitle } from "../documentTitle.js";
2
+ import pages_module_default from "./pages.module.js";
3
+ import { LinkButton } from "./PageHeader.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { appMessages } from "@panneau/intl";
6
+ import { Heading, usePanneauIntl } from "@panneau/ui";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/pages/NotFoundPage.tsx
9
+ /** The page of the paths that match no route, resource or page. */
10
+ function NotFoundPage(t0) {
11
+ const $ = c(21);
12
+ const { homeHref } = t0;
13
+ const intl = usePanneauIntl();
14
+ let t1;
15
+ if ($[0] !== intl) {
16
+ t1 = intl.formatMessage(appMessages.notFound);
17
+ $[0] = intl;
18
+ $[1] = t1;
19
+ } else t1 = $[1];
20
+ let t2;
21
+ if ($[2] !== t1) {
22
+ t2 = [t1];
23
+ $[2] = t1;
24
+ $[3] = t2;
25
+ } else t2 = $[3];
26
+ useDocumentTitle(t2);
27
+ let t3;
28
+ if ($[4] !== intl) {
29
+ t3 = intl.formatMessage(appMessages.notFound);
30
+ $[4] = intl;
31
+ $[5] = t3;
32
+ } else t3 = $[5];
33
+ let t4;
34
+ if ($[6] !== t3) {
35
+ t4 = /* @__PURE__ */ jsx(Heading, {
36
+ level: 1,
37
+ children: t3
38
+ });
39
+ $[6] = t3;
40
+ $[7] = t4;
41
+ } else t4 = $[7];
42
+ let t5;
43
+ if ($[8] !== intl) {
44
+ t5 = intl.formatMessage(appMessages.notFoundText);
45
+ $[8] = intl;
46
+ $[9] = t5;
47
+ } else t5 = $[9];
48
+ let t6;
49
+ if ($[10] !== t5) {
50
+ t6 = /* @__PURE__ */ jsx("p", {
51
+ className: pages_module_default.intro,
52
+ children: t5
53
+ });
54
+ $[10] = t5;
55
+ $[11] = t6;
56
+ } else t6 = $[11];
57
+ let t7;
58
+ if ($[12] !== intl) {
59
+ t7 = intl.formatMessage(appMessages.backHome);
60
+ $[12] = intl;
61
+ $[13] = t7;
62
+ } else t7 = $[13];
63
+ let t8;
64
+ if ($[14] !== homeHref || $[15] !== t7) {
65
+ t8 = /* @__PURE__ */ jsx(LinkButton, {
66
+ href: homeHref,
67
+ children: t7
68
+ });
69
+ $[14] = homeHref;
70
+ $[15] = t7;
71
+ $[16] = t8;
72
+ } else t8 = $[16];
73
+ let t9;
74
+ if ($[17] !== t4 || $[18] !== t6 || $[19] !== t8) {
75
+ t9 = /* @__PURE__ */ jsxs("div", {
76
+ className: pages_module_default.center,
77
+ children: [
78
+ t4,
79
+ t6,
80
+ t8
81
+ ]
82
+ });
83
+ $[17] = t4;
84
+ $[18] = t6;
85
+ $[19] = t8;
86
+ $[20] = t9;
87
+ } else t9 = $[20];
88
+ return t9;
89
+ }
90
+ //#endregion
91
+ export { NotFoundPage };
92
+
93
+ //# sourceMappingURL=NotFoundPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotFoundPage.js","names":["homeHref","_c","styles"],"sources":["../../src/pages/NotFoundPage.tsx"],"sourcesContent":["import { appMessages } from '@panneau/intl';\nimport { Heading, usePanneauIntl } from '@panneau/ui';\n\nimport { useDocumentTitle } from '../documentTitle';\nimport { LinkButton } from './PageHeader';\nimport styles from './pages.module.css';\n\nexport interface NotFoundPageProps {\n homeHref: string;\n}\n\n/** The page of the paths that match no route, resource or page. */\nexport function NotFoundPage({ homeHref }: NotFoundPageProps) {\n const intl = usePanneauIntl();\n useDocumentTitle([intl.formatMessage(appMessages.notFound)]);\n return (\n <div className={styles.center}>\n <Heading level={1}>{intl.formatMessage(appMessages.notFound)}</Heading>\n <p className={styles.intro}>{intl.formatMessage(appMessages.notFoundText)}</p>\n <LinkButton href={homeHref}>{intl.formatMessage(appMessages.backHome)}</LinkButton>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAYA,SAAO,aAAA,IAAA;CAAA,MAAA,IAAAC,EAAA,EAAA;CAAsB,MAAA,EAAA,aAAA;CACzB,MAAA,OAAa,eAAe;CAAE,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EACZ,KAAA,KAAI,cAAe,YAAW,QAAS;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,IAAA;EAAzC,KAAA,CAAC,EAAwC;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAA3D,iBAAiB,EAA0C;CAAC,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EAGhC,KAAA,KAAI,cAAe,YAAW,QAAS;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,IAAA;EAA5D,KAAA,oBAAC,SAAD;GAAgB,OAAA;GAAI,UAAA;EAAZ,CAAA;EAA+D,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EAC1C,KAAA,KAAI,cAAe,YAAW,YAAa;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,IAAA;EAAzE,KAAA,oBAAA,KAAA;GAAc,WAAAC,qBAAM;GAAS,UAAA;EAAiD,CAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,MAAA;EACjD,KAAA,KAAI,cAAe,YAAW,QAAS;EAAC,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,YAAA,EAAA,QAAA,IAAA;EAArE,KAAA,oBAAC,YAAD;GAAkBF,MAAA;GAAW,UAAA;EAAlB,CAAA;EAAwE,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,IAAA;EAHvF,KAAA,qBAAA,OAAA;GAAgB,WAAAE,qBAAM;GAAtB,UAAA;IACI;IACA;IACA;GACE;;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAJN;AAIM"}
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface PageHeaderProps {
3
+ title: ReactNode;
4
+ /** A link to the parent page, above the title. */
5
+ back?: {
6
+ href: string;
7
+ label: string;
8
+ };
9
+ /** Buttons and links at the end of the header. */
10
+ actions?: ReactNode;
11
+ }
12
+ /** The title of a page, with a link to its parent page and its actions. */
13
+ export declare function PageHeader({ title, back, actions }: PageHeaderProps): import("react").JSX.Element;
14
+ export interface LinkButtonProps {
15
+ href: string;
16
+ icon?: ReactNode;
17
+ children: ReactNode;
18
+ }
19
+ /** A link that looks like the primary button. */
20
+ export declare function LinkButton({ href, icon, children }: LinkButtonProps): import("react").JSX.Element;
21
+ //# sourceMappingURL=PageHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.d.ts","sourceRoot":"","sources":["../../src/pages/PageHeader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB,kDAAkD;IAClD,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,kDAAkD;IAClD,OAAO,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,2EAA2E;AAC3E,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,eAAe,+BAenE;AAED,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACvB;AAED,iDAAiD;AACjD,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,eAAe,+BAOnE"}
@@ -0,0 +1,86 @@
1
+ import pages_module_default from "./pages.module.js";
2
+ import { c } from "react/compiler-runtime";
3
+ import { Heading, Icon } from "@panneau/ui";
4
+ import { Link } from "react-aria-components";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { ChevronLeft } from "lucide-react";
7
+ //#region src/pages/PageHeader.tsx
8
+ /** The title of a page, with a link to its parent page and its actions. */
9
+ function PageHeader(t0) {
10
+ const $ = c(12);
11
+ const { title, back, actions } = t0;
12
+ let t1;
13
+ if ($[0] !== back) {
14
+ t1 = back !== void 0 ? /* @__PURE__ */ jsxs(Link, {
15
+ href: back.href,
16
+ className: pages_module_default.back,
17
+ children: [/* @__PURE__ */ jsx(Icon, {
18
+ icon: ChevronLeft,
19
+ size: "sm"
20
+ }), back.label]
21
+ }) : null;
22
+ $[0] = back;
23
+ $[1] = t1;
24
+ } else t1 = $[1];
25
+ let t2;
26
+ if ($[2] !== title) {
27
+ t2 = /* @__PURE__ */ jsx(Heading, {
28
+ level: 1,
29
+ children: title
30
+ });
31
+ $[2] = title;
32
+ $[3] = t2;
33
+ } else t2 = $[3];
34
+ let t3;
35
+ if ($[4] !== t1 || $[5] !== t2) {
36
+ t3 = /* @__PURE__ */ jsxs("div", {
37
+ className: pages_module_default.headerTitle,
38
+ children: [t1, t2]
39
+ });
40
+ $[4] = t1;
41
+ $[5] = t2;
42
+ $[6] = t3;
43
+ } else t3 = $[6];
44
+ let t4;
45
+ if ($[7] !== actions) {
46
+ t4 = actions !== void 0 ? /* @__PURE__ */ jsx("div", {
47
+ className: pages_module_default.headerActions,
48
+ children: actions
49
+ }) : null;
50
+ $[7] = actions;
51
+ $[8] = t4;
52
+ } else t4 = $[8];
53
+ let t5;
54
+ if ($[9] !== t3 || $[10] !== t4) {
55
+ t5 = /* @__PURE__ */ jsxs("header", {
56
+ className: pages_module_default.header,
57
+ children: [t3, t4]
58
+ });
59
+ $[9] = t3;
60
+ $[10] = t4;
61
+ $[11] = t5;
62
+ } else t5 = $[11];
63
+ return t5;
64
+ }
65
+ /** A link that looks like the primary button. */
66
+ function LinkButton(t0) {
67
+ const $ = c(4);
68
+ const { href, icon, children } = t0;
69
+ let t1;
70
+ if ($[0] !== children || $[1] !== href || $[2] !== icon) {
71
+ t1 = /* @__PURE__ */ jsxs(Link, {
72
+ href,
73
+ className: pages_module_default.linkButton,
74
+ children: [icon, children]
75
+ });
76
+ $[0] = children;
77
+ $[1] = href;
78
+ $[2] = icon;
79
+ $[3] = t1;
80
+ } else t1 = $[3];
81
+ return t1;
82
+ }
83
+ //#endregion
84
+ export { LinkButton, PageHeader };
85
+
86
+ //# sourceMappingURL=PageHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.js","names":["ChevronLeft","title","actions","href","icon","children","_c","styles"],"sources":["../../src/pages/PageHeader.tsx"],"sourcesContent":["import { ChevronLeft } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { Link } from 'react-aria-components';\n\nimport { Heading, Icon } from '@panneau/ui';\n\nimport styles from './pages.module.css';\n\nexport interface PageHeaderProps {\n title: ReactNode;\n /** A link to the parent page, above the title. */\n back?: { href: string; label: string };\n /** Buttons and links at the end of the header. */\n actions?: ReactNode;\n}\n\n/** The title of a page, with a link to its parent page and its actions. */\nexport function PageHeader({ title, back, actions }: PageHeaderProps) {\n return (\n <header className={styles.header}>\n <div className={styles.headerTitle}>\n {back !== undefined ? (\n <Link href={back.href} className={styles.back}>\n <Icon icon={ChevronLeft} size=\"sm\" />\n {back.label}\n </Link>\n ) : null}\n <Heading level={1}>{title}</Heading>\n </div>\n {actions !== undefined ? <div className={styles.headerActions}>{actions}</div> : null}\n </header>\n );\n}\n\nexport interface LinkButtonProps {\n href: string;\n icon?: ReactNode;\n children: ReactNode;\n}\n\n/** A link that looks like the primary button. */\nexport function LinkButton({ href, icon, children }: LinkButtonProps) {\n return (\n <Link href={href} className={styles.linkButton}>\n {icon}\n {children}\n </Link>\n );\n}\n"],"mappings":";;;;;;;;AAiBA,SAAO,WAAA,IAAA;CAAA,MAAA,IAAAM,EAAA,EAAA;CAAoB,MAAA,EAAA,OAAA,MAAA,YAAA;CAAyC,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EAInD,KAAA,SAAS,KAAA,IACN,qBAAC,MAAD;GAAY,MAAA,KAAI;GAAkB,WAAAC,qBAAM;GAAxC,UAAA,CACI,oBAAC,MAAD;IAAYP,MAAA;IAAkB,MAAA;GAAI,CAAA,GACjC,KAAI,KAFJ;EADR,CAAA,IAAA;EAKO,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EACR,KAAA,oBAAC,SAAD;GAAgB,OAAA;GAAI,UAAA;EAAZ,CAAA;EAA4B,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA,EAAA,OAAA,IAAA;EAPxC,KAAA,qBAAA,OAAA;GAAgB,WAAAO,qBAAM;GAAtB,UAAA,CACK,IAMD,EACE;;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,SAAA;EACL,KAAA,YAAY,KAAA,IAAY,oBAAA,OAAA;GAAgB,WAAAA,qBAAM;GAAiB,UAAA;EAAc,CAAA,IAA7E;EAAoF,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA,EAAA,QAAA,IAAA;EAVzF,KAAA,qBAAA,UAAA;GAAmB,WAAAA,qBAAM;GAAzB,UAAA,CACI,IASC,EACI;;EAAA,EAAA,KAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAXT;AAWS;;AAWjB,SAAO,WAAA,IAAA;CAAA,MAAA,IAAAD,EAAA,CAAA;CAAoB,MAAA,EAAA,MAAA,MAAA,aAAA;CAAyC,IAAA;CAAA,IAAA,EAAA,OAAA,YAAA,EAAA,OAAA,QAAA,EAAA,OAAA,MAAA;EAE5D,KAAA,qBAAC,MAAD;GAAY;GAAiB,WAAAC,qBAAM;GAAnC,UAAA,CACK,MACA,QAFA;;EAGE,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAHP;AAGO"}
@@ -0,0 +1,15 @@
1
+ import { type ResolvedResource } from '@panneau/core';
2
+ import type { Definition } from '@panneau/protocol';
3
+ export interface ResourceFormPageProps {
4
+ definition: Definition;
5
+ resolved: ResolvedResource;
6
+ basePath: string;
7
+ /** The item to edit, or `null` to create one. */
8
+ id: string | null;
9
+ }
10
+ /**
11
+ * The form to create or edit an item: saved through the adapter, with validation errors from the
12
+ * server, version conflicts and a guard on unsaved changes. A new item opens in its edit page.
13
+ */
14
+ export declare function ResourceFormPage({ definition, resolved, basePath, id }: ResourceFormPageProps): import("react").JSX.Element;
15
+ //# sourceMappingURL=ResourceFormPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceFormPage.d.ts","sourceRoot":"","sources":["../../src/pages/ResourceFormPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,eAAe,CAAC;AAKlF,OAAO,KAAK,EAAE,UAAU,EAAQ,MAAM,mBAAmB,CAAC;AAY1D,MAAM,WAAW,qBAAqB;IAClC,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,qBAAqB,+BAgG7F"}
@@ -0,0 +1,204 @@
1
+ import { useDocumentTitle } from "../documentTitle.js";
2
+ import { navigate } from "../location.js";
3
+ import { routePath } from "../routes.js";
4
+ import { capitalize } from "../navigation.js";
5
+ import pages_module_default from "./pages.module.js";
6
+ import { PageHeader } from "./PageHeader.js";
7
+ import { useRecordRecentItem } from "../recentItems.js";
8
+ import { getItemTitle } from "./itemTitle.js";
9
+ import { c } from "react/compiler-runtime";
10
+ import { getItemValues, resolveForm } from "@panneau/core";
11
+ import { useCreateItem, useDataAdapter, useResourceItem, useUpdateItem } from "@panneau/data/query";
12
+ import { appMessages } from "@panneau/intl";
13
+ import { Alert, Button, Spinner, usePanneauIntl } from "@panneau/ui";
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ import { createRelationSource } from "@panneau/fields";
16
+ import { Form } from "@panneau/forms";
17
+ //#region src/pages/ResourceFormPage.tsx
18
+ /**
19
+ * The form to create or edit an item: saved through the adapter, with validation errors from the
20
+ * server, version conflicts and a guard on unsaved changes. A new item opens in its edit page.
21
+ */
22
+ function ResourceFormPage(t0) {
23
+ const $ = c(48);
24
+ const { definition, resolved, basePath, id } = t0;
25
+ const intl = usePanneauIntl();
26
+ const adapter = useDataAdapter();
27
+ const { resource } = resolved;
28
+ const mode = id === null ? "create" : "update";
29
+ const itemQuery = useResourceItem(resource.id, id);
30
+ const createItem = useCreateItem(resource.id);
31
+ const updateItem = useUpdateItem(resource.id);
32
+ let t1;
33
+ if ($[0] !== adapter || $[1] !== definition) {
34
+ t1 = createRelationSource(adapter, { definition });
35
+ $[0] = adapter;
36
+ $[1] = definition;
37
+ $[2] = t1;
38
+ } else t1 = $[2];
39
+ const relationSource = t1;
40
+ const { fields, layout } = resolveForm(resource, { mode });
41
+ const item = itemQuery.data;
42
+ const singular = resource.label.singular;
43
+ let t2;
44
+ if ($[3] !== definition.locale || $[4] !== intl || $[5] !== item || $[6] !== mode || $[7] !== resource.itemTitle || $[8] !== singular) {
45
+ t2 = mode === "create" ? intl.formatMessage(appMessages.create, { resource: singular }) : getItemTitle(item, resource.itemTitle, definition.locale) ?? intl.formatMessage(appMessages.edit, { resource: singular });
46
+ $[3] = definition.locale;
47
+ $[4] = intl;
48
+ $[5] = item;
49
+ $[6] = mode;
50
+ $[7] = resource.itemTitle;
51
+ $[8] = singular;
52
+ $[9] = t2;
53
+ } else t2 = $[9];
54
+ const title = t2;
55
+ let t3;
56
+ if ($[10] !== definition.locale || $[11] !== id || $[12] !== item || $[13] !== resource.id || $[14] !== resource.itemTitle) {
57
+ t3 = id !== null && item !== void 0 ? {
58
+ resource: resource.id,
59
+ id,
60
+ title: getItemTitle(item, resource.itemTitle, definition.locale) ?? id
61
+ } : null;
62
+ $[10] = definition.locale;
63
+ $[11] = id;
64
+ $[12] = item;
65
+ $[13] = resource.id;
66
+ $[14] = resource.itemTitle;
67
+ $[15] = t3;
68
+ } else t3 = $[15];
69
+ useRecordRecentItem(basePath, t3);
70
+ let t4;
71
+ if ($[16] !== basePath || $[17] !== resource.id) {
72
+ t4 = routePath({
73
+ name: "resource.index",
74
+ resource: resource.id
75
+ }, basePath);
76
+ $[16] = basePath;
77
+ $[17] = resource.id;
78
+ $[18] = t4;
79
+ } else t4 = $[18];
80
+ let t5;
81
+ if ($[19] !== definition.locale || $[20] !== resource.label.plural) {
82
+ t5 = capitalize(resource.label.plural, definition.locale);
83
+ $[19] = definition.locale;
84
+ $[20] = resource.label.plural;
85
+ $[21] = t5;
86
+ } else t5 = $[21];
87
+ let t6;
88
+ if ($[22] !== t4 || $[23] !== t5) {
89
+ t6 = {
90
+ href: t4,
91
+ label: t5
92
+ };
93
+ $[22] = t4;
94
+ $[23] = t5;
95
+ $[24] = t6;
96
+ } else t6 = $[24];
97
+ const back = t6;
98
+ let t7;
99
+ if ($[25] !== back.label || $[26] !== title) {
100
+ t7 = [title, back.label];
101
+ $[25] = back.label;
102
+ $[26] = title;
103
+ $[27] = t7;
104
+ } else t7 = $[27];
105
+ useDocumentTitle(t7);
106
+ let content;
107
+ if (mode === "update" && item === void 0) {
108
+ let t8;
109
+ if ($[28] !== intl || $[29] !== itemQuery || $[30] !== singular) {
110
+ t8 = itemQuery.isError ? /* @__PURE__ */ jsxs(Alert, {
111
+ tone: "danger",
112
+ children: [/* @__PURE__ */ jsx("p", { children: intl.formatMessage(appMessages.itemLoadError, { resource: singular }) }), /* @__PURE__ */ jsx(Button, {
113
+ size: "sm",
114
+ onPress: () => void itemQuery.refetch(),
115
+ children: intl.formatMessage(appMessages.retry)
116
+ })]
117
+ }) : /* @__PURE__ */ jsx(Spinner, { showLabel: true });
118
+ $[28] = intl;
119
+ $[29] = itemQuery;
120
+ $[30] = singular;
121
+ $[31] = t8;
122
+ } else t8 = $[31];
123
+ content = t8;
124
+ } else {
125
+ let t8;
126
+ if ($[32] !== createItem || $[33] !== id || $[34] !== updateItem) {
127
+ t8 = (values, t9) => {
128
+ const { version, changes } = t9;
129
+ return id === null ? createItem.mutateAsync(values) : updateItem.mutateAsync({
130
+ id,
131
+ values: changes,
132
+ version
133
+ });
134
+ };
135
+ $[32] = createItem;
136
+ $[33] = id;
137
+ $[34] = updateItem;
138
+ $[35] = t8;
139
+ } else t8 = $[35];
140
+ let t9;
141
+ if ($[36] !== basePath || $[37] !== id || $[38] !== resource.id) {
142
+ t9 = (result) => {
143
+ if (id === null) navigate(routePath({
144
+ name: "resource.edit",
145
+ resource: resource.id,
146
+ id: result.id
147
+ }, basePath));
148
+ };
149
+ $[36] = basePath;
150
+ $[37] = id;
151
+ $[38] = resource.id;
152
+ $[39] = t9;
153
+ } else t9 = $[39];
154
+ let t10;
155
+ if ($[40] !== itemQuery) {
156
+ t10 = () => void itemQuery.refetch();
157
+ $[40] = itemQuery;
158
+ $[41] = t10;
159
+ } else t10 = $[41];
160
+ content = /* @__PURE__ */ jsx(Form, {
161
+ "aria-label": title,
162
+ fields,
163
+ layout,
164
+ values: item !== void 0 ? getItemValues(item, fields.map(_temp)) : void 0,
165
+ version: item?.version ?? null,
166
+ mode,
167
+ locales: definition.locales,
168
+ relationSource,
169
+ guardUnsavedChanges: true,
170
+ showSavedToast: true,
171
+ onSubmit: t8,
172
+ onSubmitted: t9,
173
+ onReload: t10
174
+ }, item?.version ?? item?.id ?? "new");
175
+ }
176
+ let t8;
177
+ if ($[42] !== back || $[43] !== title) {
178
+ t8 = /* @__PURE__ */ jsx(PageHeader, {
179
+ title,
180
+ back
181
+ });
182
+ $[42] = back;
183
+ $[43] = title;
184
+ $[44] = t8;
185
+ } else t8 = $[44];
186
+ let t9;
187
+ if ($[45] !== content || $[46] !== t8) {
188
+ t9 = /* @__PURE__ */ jsxs("div", {
189
+ className: `${pages_module_default.page} ${pages_module_default.narrow}`,
190
+ children: [t8, content]
191
+ });
192
+ $[45] = content;
193
+ $[46] = t8;
194
+ $[47] = t9;
195
+ } else t9 = $[47];
196
+ return t9;
197
+ }
198
+ function _temp(field) {
199
+ return field.name;
200
+ }
201
+ //#endregion
202
+ export { ResourceFormPage };
203
+
204
+ //# sourceMappingURL=ResourceFormPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceFormPage.js","names":["content","title","fields","layout","mode","relationSource","back","_c","styles"],"sources":["../../src/pages/ResourceFormPage.tsx"],"sourcesContent":["import { type ResolvedResource, getItemValues, resolveForm } from '@panneau/core';\nimport { useCreateItem, useDataAdapter, useResourceItem, useUpdateItem } from '@panneau/data/query';\nimport { createRelationSource } from '@panneau/fields';\nimport { Form } from '@panneau/forms';\nimport { appMessages } from '@panneau/intl';\nimport type { Definition, Item } from '@panneau/protocol';\nimport { Alert, Button, Spinner, usePanneauIntl } from '@panneau/ui';\n\nimport { useDocumentTitle } from '../documentTitle';\nimport { navigate } from '../location';\nimport { capitalize } from '../navigation';\nimport { useRecordRecentItem } from '../recentItems';\nimport { routePath } from '../routes';\nimport { PageHeader } from './PageHeader';\nimport { getItemTitle } from './itemTitle';\nimport styles from './pages.module.css';\n\nexport interface ResourceFormPageProps {\n definition: Definition;\n resolved: ResolvedResource;\n basePath: string;\n /** The item to edit, or `null` to create one. */\n id: string | null;\n}\n\n/**\n * The form to create or edit an item: saved through the adapter, with validation errors from the\n * server, version conflicts and a guard on unsaved changes. A new item opens in its edit page.\n */\nexport function ResourceFormPage({ definition, resolved, basePath, id }: ResourceFormPageProps) {\n const intl = usePanneauIntl();\n const adapter = useDataAdapter();\n const { resource } = resolved;\n const mode = id === null ? 'create' : 'update';\n const itemQuery = useResourceItem(resource.id, id);\n const createItem = useCreateItem(resource.id);\n const updateItem = useUpdateItem(resource.id);\n const relationSource = createRelationSource(adapter, { definition });\n const { fields, layout } = resolveForm(resource, { mode });\n const item = itemQuery.data;\n const singular = resource.label.singular;\n const title =\n mode === 'create'\n ? intl.formatMessage(appMessages.create, { resource: singular })\n : (getItemTitle(item, resource.itemTitle, definition.locale) ??\n intl.formatMessage(appMessages.edit, { resource: singular }));\n useRecordRecentItem(\n basePath,\n id !== null && item !== undefined\n ? {\n resource: resource.id,\n id,\n title: getItemTitle(item, resource.itemTitle, definition.locale) ?? id,\n }\n : null,\n );\n const back = {\n href: routePath({ name: 'resource.index', resource: resource.id }, basePath),\n label: capitalize(resource.label.plural, definition.locale),\n };\n useDocumentTitle([title, back.label]);\n\n let content;\n if (mode === 'update' && item === undefined) {\n content = itemQuery.isError ? (\n <Alert tone=\"danger\">\n <p>{intl.formatMessage(appMessages.itemLoadError, { resource: singular })}</p>\n <Button size=\"sm\" onPress={() => void itemQuery.refetch()}>\n {intl.formatMessage(appMessages.retry)}\n </Button>\n </Alert>\n ) : (\n <Spinner showLabel />\n );\n } else {\n content = (\n <Form\n key={item?.version ?? item?.id ?? 'new'}\n aria-label={title}\n fields={fields}\n layout={layout}\n values={\n item !== undefined\n ? getItemValues(\n item,\n fields.map((field) => field.name),\n )\n : undefined\n }\n version={item?.version ?? null}\n mode={mode}\n locales={definition.locales}\n relationSource={relationSource}\n guardUnsavedChanges\n showSavedToast\n onSubmit={(values, { version, changes }) =>\n id === null\n ? createItem.mutateAsync(values)\n : updateItem.mutateAsync({ id, values: changes, version })\n }\n onSubmitted={(result) => {\n if (id === null) {\n navigate(\n routePath(\n {\n name: 'resource.edit',\n resource: resource.id,\n id: (result as Item).id,\n },\n basePath,\n ),\n );\n }\n }}\n onReload={() => void itemQuery.refetch()}\n />\n );\n }\n\n return (\n <div className={`${styles.page} ${styles.narrow}`}>\n <PageHeader title={title} back={back} />\n {content}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type ResolvedResource } from '@panneau/core';
2
+ export interface ResourceListPageProps {
3
+ resolved: ResolvedResource;
4
+ basePath: string;
5
+ locale: string;
6
+ /** The item shown in a panel next to the list (the show route), or `null`. */
7
+ selectedId?: string | null;
8
+ }
9
+ /**
10
+ * The list of a resource: its query in the URL, its items fetched through the adapter, and its
11
+ * actions run by the action runner. Rendered with a `key` per resource, so each one keeps its own
12
+ * list state.
13
+ */
14
+ export declare function ResourceListPage({ resolved, basePath, locale, selectedId, }: ResourceListPageProps): import("react").JSX.Element;
15
+ //# sourceMappingURL=ResourceListPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceListPage.d.ts","sourceRoot":"","sources":["../../src/pages/ResourceListPage.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAAW,MAAM,eAAe,CAAC;AAe/D,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,UAAiB,GACpB,EAAE,qBAAqB,+BA8EvB"}
@@ -0,0 +1,101 @@
1
+ import { useDocumentTitle } from "../documentTitle.js";
2
+ import { routePath } from "../routes.js";
3
+ import { capitalize } from "../navigation.js";
4
+ import pages_module_default from "./pages.module.js";
5
+ import { LinkButton, PageHeader } from "./PageHeader.js";
6
+ import { getItemTitle } from "./itemTitle.js";
7
+ import { cx } from "../cx.js";
8
+ import { ItemPanel } from "./ItemPanel.js";
9
+ import { useList } from "@panneau/core";
10
+ import { useResourceItem, useResourceList } from "@panneau/data/query";
11
+ import { appMessages } from "@panneau/intl";
12
+ import { Icon, usePanneauIntl } from "@panneau/ui";
13
+ import { useActionPreview, useActionRunner } from "@panneau/actions";
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ import { Plus } from "lucide-react";
16
+ import { ListView } from "@panneau/lists";
17
+ //#region src/pages/ResourceListPage.tsx
18
+ /**
19
+ * The list of a resource: its query in the URL, its items fetched through the adapter, and its
20
+ * actions run by the action runner. Rendered with a `key` per resource, so each one keeps its own
21
+ * list state.
22
+ */
23
+ function ResourceListPage({ resolved, basePath, locale, selectedId = null }) {
24
+ const intl = usePanneauIntl();
25
+ const { resource, list: definitionList, abilities } = resolved;
26
+ const { query, list } = useList({ list: definitionList });
27
+ const { data, error, isFetching, refetch } = useResourceList(resource.id, query, { placeholderData: (previous) => previous });
28
+ const runAction = useActionRunner(resource.id);
29
+ const previewAction = useActionPreview(resource.id);
30
+ const title = capitalize(resource.label.plural, locale);
31
+ const { data: selected } = useResourceItem(resource.id, selectedId);
32
+ useDocumentTitle([selectedId !== null ? getItemTitle(selected, resource.itemTitle, locale) ?? selectedId : null, title]);
33
+ const search = window.location.search;
34
+ const indexPath = routePath({
35
+ name: "resource.index",
36
+ resource: resource.id
37
+ }, basePath);
38
+ return /* @__PURE__ */ jsxs("div", {
39
+ className: cx(pages_module_default.page, selectedId !== null && pages_module_default.withPanel),
40
+ children: [
41
+ /* @__PURE__ */ jsx(PageHeader, {
42
+ title,
43
+ actions: abilities.create ? /* @__PURE__ */ jsx(LinkButton, {
44
+ href: routePath({
45
+ name: "resource.create",
46
+ resource: resource.id
47
+ }, basePath),
48
+ icon: /* @__PURE__ */ jsx(Icon, {
49
+ icon: Plus,
50
+ size: "md"
51
+ }),
52
+ children: intl.formatMessage(appMessages.create, { resource: resource.label.singular })
53
+ }) : void 0
54
+ }),
55
+ resource.description !== void 0 ? /* @__PURE__ */ jsx("p", {
56
+ className: pages_module_default.intro,
57
+ children: resource.description
58
+ }) : null,
59
+ /* @__PURE__ */ jsxs("div", {
60
+ className: pages_module_default.split,
61
+ children: [/* @__PURE__ */ jsx(ListView, {
62
+ ...definitionList,
63
+ "aria-label": title,
64
+ list,
65
+ items: data?.data,
66
+ total: data?.meta.total,
67
+ isLoading: isFetching,
68
+ error,
69
+ onRetry: () => void refetch(),
70
+ fields: resource.fields,
71
+ itemTitle: resource.itemTitle,
72
+ layouts: ["table", "cards"],
73
+ perPageOptions: [
74
+ 10,
75
+ 20,
76
+ 50,
77
+ 100
78
+ ],
79
+ getItemHref: (item) => `${routePath({
80
+ name: "resource.show",
81
+ resource: resource.id,
82
+ id: item.id
83
+ }, basePath)}${search}`,
84
+ currentItemId: selectedId,
85
+ onAction: runAction,
86
+ previewAction
87
+ }), selectedId !== null ? /* @__PURE__ */ jsx(ItemPanel, {
88
+ resolved,
89
+ basePath,
90
+ locale,
91
+ id: selectedId,
92
+ closeHref: `${indexPath}${search}`
93
+ }, selectedId) : null]
94
+ })
95
+ ]
96
+ });
97
+ }
98
+ //#endregion
99
+ export { ResourceListPage };
100
+
101
+ //# sourceMappingURL=ResourceListPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceListPage.js","names":["styles"],"sources":["../../src/pages/ResourceListPage.tsx"],"sourcesContent":["import { Plus } from 'lucide-react';\n\nimport { useActionPreview, useActionRunner } from '@panneau/actions';\nimport { type ResolvedResource, useList } from '@panneau/core';\nimport { useResourceItem, useResourceList } from '@panneau/data/query';\nimport { appMessages } from '@panneau/intl';\nimport { ListView } from '@panneau/lists';\nimport { Icon, usePanneauIntl } from '@panneau/ui';\n\nimport { cx } from '../cx';\nimport { useDocumentTitle } from '../documentTitle';\nimport { capitalize } from '../navigation';\nimport { routePath } from '../routes';\nimport { ItemPanel } from './ItemPanel';\nimport { LinkButton, PageHeader } from './PageHeader';\nimport { getItemTitle } from './itemTitle';\nimport styles from './pages.module.css';\n\nexport interface ResourceListPageProps {\n resolved: ResolvedResource;\n basePath: string;\n locale: string;\n /** The item shown in a panel next to the list (the show route), or `null`. */\n selectedId?: string | null;\n}\n\n/**\n * The list of a resource: its query in the URL, its items fetched through the adapter, and its\n * actions run by the action runner. Rendered with a `key` per resource, so each one keeps its own\n * list state.\n */\nexport function ResourceListPage({\n resolved,\n basePath,\n locale,\n selectedId = null,\n}: ResourceListPageProps) {\n const intl = usePanneauIntl();\n const { resource, list: definitionList, abilities } = resolved;\n const { query, list } = useList({ list: definitionList });\n const { data, error, isFetching, refetch } = useResourceList(resource.id, query, {\n placeholderData: (previous) => previous,\n });\n const runAction = useActionRunner(resource.id);\n const previewAction = useActionPreview(resource.id);\n const title = capitalize(resource.label.plural, locale);\n // The item of the panel, which the panel fetches too\n const { data: selected } = useResourceItem(resource.id, selectedId);\n useDocumentTitle([\n selectedId !== null\n ? (getItemTitle(selected, resource.itemTitle, locale) ?? selectedId)\n : null,\n title,\n ]);\n // The list keeps its query in the URL: the panel opens and closes without losing it.\n const search = window.location.search;\n const indexPath = routePath({ name: 'resource.index', resource: resource.id }, basePath);\n return (\n <div className={cx(styles.page, selectedId !== null && styles.withPanel)}>\n <PageHeader\n title={title}\n actions={\n abilities.create ? (\n <LinkButton\n href={routePath(\n { name: 'resource.create', resource: resource.id },\n basePath,\n )}\n icon={<Icon icon={Plus} size=\"md\" />}\n >\n {intl.formatMessage(appMessages.create, {\n resource: resource.label.singular,\n })}\n </LinkButton>\n ) : undefined\n }\n />\n {resource.description !== undefined ? (\n <p className={styles.intro}>{resource.description}</p>\n ) : null}\n <div className={styles.split}>\n <ListView\n {...definitionList}\n aria-label={title}\n list={list}\n items={data?.data}\n total={data?.meta.total}\n isLoading={isFetching}\n error={error}\n onRetry={() => void refetch()}\n fields={resource.fields}\n itemTitle={resource.itemTitle}\n layouts={['table', 'cards']}\n perPageOptions={[10, 20, 50, 100]}\n getItemHref={(item) =>\n `${routePath({ name: 'resource.show', resource: resource.id, id: item.id }, basePath)}${search}`\n }\n currentItemId={selectedId}\n onAction={runAction}\n previewAction={previewAction}\n />\n {selectedId !== null ? (\n <ItemPanel\n key={selectedId}\n resolved={resolved}\n basePath={basePath}\n locale={locale}\n id={selectedId}\n closeHref={`${indexPath}${search}`}\n />\n ) : null}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,iBAAiB,EAC7B,UACA,UACA,QACA,aAAa,QACS;CACtB,MAAM,OAAO,eAAe;CAC5B,MAAM,EAAE,UAAU,MAAM,gBAAgB,cAAc;CACtD,MAAM,EAAE,OAAO,SAAS,QAAQ,EAAE,MAAM,eAAe,CAAC;CACxD,MAAM,EAAE,MAAM,OAAO,YAAY,YAAY,gBAAgB,SAAS,IAAI,OAAO,EAC7E,kBAAkB,aAAa,SACnC,CAAC;CACD,MAAM,YAAY,gBAAgB,SAAS,EAAE;CAC7C,MAAM,gBAAgB,iBAAiB,SAAS,EAAE;CAClD,MAAM,QAAQ,WAAW,SAAS,MAAM,QAAQ,MAAM;CAEtD,MAAM,EAAE,MAAM,aAAa,gBAAgB,SAAS,IAAI,UAAU;CAClE,iBAAiB,CACb,eAAe,OACR,aAAa,UAAU,SAAS,WAAW,MAAM,KAAK,aACvD,MACN,KAAK,CACR;CAED,MAAM,SAAS,OAAO,SAAS;CAC/B,MAAM,YAAY,UAAU;EAAE,MAAM;EAAkB,UAAU,SAAS;CAAG,GAAG,QAAQ;CACvF,OACI,qBAAC,OAAD;EAAK,WAAW,GAAGA,qBAAO,MAAM,eAAe,QAAQA,qBAAO,SAAS;EAAvE,UAAA;GACI,oBAAC,YAAD;IACW;IACP,SACI,UAAU,SACN,oBAAC,YAAD;KACI,MAAM,UACF;MAAE,MAAM;MAAmB,UAAU,SAAS;KAAG,GACjD,QACJ;KACA,MAAM,oBAAC,MAAD;MAAM,MAAM;MAAM,MAAK;KAAI,CAAA;KAEhC,UAAA,KAAK,cAAc,YAAY,QAAQ,EACpC,UAAU,SAAS,MAAM,SAC7B,CAAC;IACO,CAAA,IACZ,KAAA;GACP,CAAA;GAEJ,SAAS,gBAAgB,KAAA,IACtB,oBAAC,KAAD;IAAG,WAAWA,qBAAO;IAAQ,UAAA,SAAS;GAAe,CAAA,IACrD;GACJ,qBAAC,OAAD;IAAK,WAAWA,qBAAO;IAAvB,UAAA,CACI,oBAAC,UAAD;KACI,GAAI;KACJ,cAAY;KACN;KACN,OAAO,MAAM;KACb,OAAO,MAAM,KAAK;KAClB,WAAW;KACJ;KACP,eAAe,KAAK,QAAQ;KAC5B,QAAQ,SAAS;KACjB,WAAW,SAAS;KACpB,SAAS,CAAC,SAAS,OAAO;KAC1B,gBAAgB;MAAC;MAAI;MAAI;MAAI;KAAG;KAChC,cAAc,SACV,GAAG,UAAU;MAAE,MAAM;MAAiB,UAAU,SAAS;MAAI,IAAI,KAAK;KAAG,GAAG,QAAQ,IAAI;KAE5F,eAAe;KACf,UAAU;KACK;IAAc,CAAA,GAEhC,eAAe,OACZ,oBAAC,WAAD;KAEc;KACA;KACF;KACR,IAAI;KACJ,WAAW,GAAG,YAAY;IAAS,GAL9B,UAK8B,IAEvC,IACH;;EACJ;;AAEb"}
@@ -0,0 +1,7 @@
1
+ import type { Item } from '@panneau/protocol';
2
+ /**
3
+ * The title of an item: the value of the resource's `itemTitle` field, in the locale when it is
4
+ * localized. `null` without one.
5
+ */
6
+ export declare function getItemTitle(item: Item | undefined, itemTitle: string | undefined, locale: string): string | null;
7
+ //# sourceMappingURL=itemTitle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"itemTitle.d.ts","sourceRoot":"","sources":["../../src/pages/itemTitle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,YAAY,CACxB,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAWf"}
@@ -0,0 +1,18 @@
1
+ //#region src/pages/itemTitle.ts
2
+ /**
3
+ * The title of an item: the value of the resource's `itemTitle` field, in the locale when it is
4
+ * localized. `null` without one.
5
+ */
6
+ function getItemTitle(item, itemTitle, locale) {
7
+ const value = itemTitle !== void 0 ? item?.[itemTitle] : void 0;
8
+ if (typeof value === "string") return value;
9
+ if (value !== null && typeof value === "object") {
10
+ const first = value[locale] ?? Object.values(value)[0];
11
+ return typeof first === "string" ? first : null;
12
+ }
13
+ return null;
14
+ }
15
+ //#endregion
16
+ export { getItemTitle };
17
+
18
+ //# sourceMappingURL=itemTitle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"itemTitle.js","names":[],"sources":["../../src/pages/itemTitle.ts"],"sourcesContent":["import type { Item } from '@panneau/protocol';\n\n/**\n * The title of an item: the value of the resource's `itemTitle` field, in the locale when it is\n * localized. `null` without one.\n */\nexport function getItemTitle(\n item: Item | undefined,\n itemTitle: string | undefined,\n locale: string,\n): string | null {\n const value = itemTitle !== undefined ? item?.[itemTitle] : undefined;\n if (typeof value === 'string') {\n return value;\n }\n if (value !== null && typeof value === 'object') {\n const localized = (value as Record<string, unknown>)[locale];\n const first = localized ?? Object.values(value)[0];\n return typeof first === 'string' ? first : null;\n }\n return null;\n}\n"],"mappings":";;;;;AAMA,SAAgB,aACZ,MACA,WACA,QACa;CACb,MAAM,QAAQ,cAAc,KAAA,IAAY,OAAO,aAAa,KAAA;CAC5D,IAAI,OAAO,UAAU,UACjB,OAAO;CAEX,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;EAE7C,MAAM,QADa,MAAkC,WAC1B,OAAO,OAAO,KAAK,CAAC,CAAC;EAChD,OAAO,OAAO,UAAU,WAAW,QAAQ;CAC/C;CACA,OAAO;AACX"}