@openrails/contentkit-ui 0.104.0-rc.1 → 0.104.0-rc.2

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 (210) hide show
  1. package/README.md +6 -6
  2. package/dist/client/beacons.js +4 -1
  3. package/dist/client/beacons.js.map +1 -1
  4. package/dist/client/contents.d.ts +7 -1
  5. package/dist/client/contents.js +8 -0
  6. package/dist/client/contents.js.map +1 -1
  7. package/dist/client/discovery.d.ts +6 -2
  8. package/dist/client/discovery.js +1 -1
  9. package/dist/client/discovery.js.map +1 -1
  10. package/dist/client/generated/routes.d.ts +41 -28
  11. package/dist/client/generated/routes.js +63 -61
  12. package/dist/client/generated/routes.js.map +1 -1
  13. package/dist/client/generated/wire.d.ts +36 -74
  14. package/dist/client/generated/wire.js.map +1 -1
  15. package/dist/client/index.d.ts +1 -1
  16. package/dist/client/media/windows.d.ts +2 -0
  17. package/dist/client/media/windows.js +4 -1
  18. package/dist/client/media/windows.js.map +1 -1
  19. package/dist/client/stats.d.ts +4 -20
  20. package/dist/client/stats.js +0 -11
  21. package/dist/client/stats.js.map +1 -1
  22. package/dist/client/versions.d.ts +8 -6
  23. package/dist/client/versions.js +15 -10
  24. package/dist/client/versions.js.map +1 -1
  25. package/dist/components/admin/bulk-drafts.d.ts +17 -0
  26. package/dist/components/admin/bulk-drafts.js +41 -0
  27. package/dist/components/admin/bulk-drafts.js.map +1 -0
  28. package/dist/components/admin/content-admin.d.ts +1 -1
  29. package/dist/components/admin/content-admin.js.map +1 -1
  30. package/dist/components/admin/content-manager.d.ts +11 -3
  31. package/dist/components/admin/content-manager.js +739 -380
  32. package/dist/components/admin/content-manager.js.map +1 -1
  33. package/dist/components/admin/group-manager.d.ts +8 -3
  34. package/dist/components/admin/group-manager.js +218 -146
  35. package/dist/components/admin/group-manager.js.map +1 -1
  36. package/dist/components/admin/page-notices.d.ts +16 -0
  37. package/dist/components/admin/page-notices.js +113 -0
  38. package/dist/components/admin/page-notices.js.map +1 -0
  39. package/dist/components/admin/page-picker.d.ts +38 -0
  40. package/dist/components/admin/page-picker.js +159 -0
  41. package/dist/components/admin/page-picker.js.map +1 -0
  42. package/dist/components/admin/reader-content-editor.js +537 -500
  43. package/dist/components/admin/reader-content-editor.js.map +1 -1
  44. package/dist/components/admin/reader-manifest.js +181 -179
  45. package/dist/components/admin/reader-manifest.js.map +1 -1
  46. package/dist/components/admin/shell.d.ts +10 -2
  47. package/dist/components/admin/shell.js +114 -42
  48. package/dist/components/admin/shell.js.map +1 -1
  49. package/dist/components/admin/stats-dashboard.d.ts +4 -9
  50. package/dist/components/admin/stats-dashboard.js +300 -202
  51. package/dist/components/admin/stats-dashboard.js.map +1 -1
  52. package/dist/components/admin/upload-queue.d.ts +14 -0
  53. package/dist/components/admin/upload-queue.js +115 -98
  54. package/dist/components/admin/upload-queue.js.map +1 -1
  55. package/dist/components/content/card.d.ts +31 -3
  56. package/dist/components/content/card.js +324 -158
  57. package/dist/components/content/card.js.map +1 -1
  58. package/dist/components/content/daily-releases.js +14 -12
  59. package/dist/components/content/daily-releases.js.map +1 -1
  60. package/dist/components/content/editor-save.js +27 -25
  61. package/dist/components/content/editor-save.js.map +1 -1
  62. package/dist/components/content/editors.js +274 -253
  63. package/dist/components/content/editors.js.map +1 -1
  64. package/dist/components/content/favorites.d.ts +1 -1
  65. package/dist/components/content/favorites.js +36 -22
  66. package/dist/components/content/favorites.js.map +1 -1
  67. package/dist/components/content/grid.d.ts +11 -4
  68. package/dist/components/content/grid.js +52 -43
  69. package/dist/components/content/grid.js.map +1 -1
  70. package/dist/components/content/history.js +83 -63
  71. package/dist/components/content/history.js.map +1 -1
  72. package/dist/components/content/index.d.ts +5 -3
  73. package/dist/components/content/listing.d.ts +14 -3
  74. package/dist/components/content/listing.js +65 -56
  75. package/dist/components/content/listing.js.map +1 -1
  76. package/dist/components/content/offer-fields.js +6 -6
  77. package/dist/components/content/paged-grid.d.ts +10 -0
  78. package/dist/components/content/paged-grid.js +116 -0
  79. package/dist/components/content/paged-grid.js.map +1 -0
  80. package/dist/components/content/pagination.d.ts +19 -0
  81. package/dist/components/content/pagination.js +97 -0
  82. package/dist/components/content/pagination.js.map +1 -0
  83. package/dist/components/content/paywall.d.ts +9 -0
  84. package/dist/components/content/paywall.js +27 -3
  85. package/dist/components/content/paywall.js.map +1 -1
  86. package/dist/components/content/post-list.d.ts +37 -0
  87. package/dist/components/content/post-list.js +203 -0
  88. package/dist/components/content/post-list.js.map +1 -0
  89. package/dist/components/content/reader-settings.d.ts +2 -0
  90. package/dist/components/content/reader-settings.js +1 -1
  91. package/dist/components/content/reader-settings.js.map +1 -1
  92. package/dist/components/groups/banner.d.ts +6 -2
  93. package/dist/components/groups/banner.js +79 -61
  94. package/dist/components/groups/banner.js.map +1 -1
  95. package/dist/components/groups/directory.d.ts +12 -2
  96. package/dist/components/groups/directory.js +168 -105
  97. package/dist/components/groups/directory.js.map +1 -1
  98. package/dist/components/groups/editor.js +10 -10
  99. package/dist/components/groups/editor.js.map +1 -1
  100. package/dist/components/groups/entity-chips.d.ts +61 -0
  101. package/dist/components/groups/entity-chips.js +382 -0
  102. package/dist/components/groups/entity-chips.js.map +1 -0
  103. package/dist/components/groups/group-members.d.ts +29 -0
  104. package/dist/components/groups/group-members.js +474 -0
  105. package/dist/components/groups/group-members.js.map +1 -0
  106. package/dist/components/groups/header.js +53 -45
  107. package/dist/components/groups/header.js.map +1 -1
  108. package/dist/components/groups/index.d.ts +3 -1
  109. package/dist/components/groups/memberships.d.ts +3 -36
  110. package/dist/components/groups/memberships.js +105 -480
  111. package/dist/components/groups/memberships.js.map +1 -1
  112. package/dist/components/groups/scoped.d.ts +23 -0
  113. package/dist/components/groups/scoped.js +92 -0
  114. package/dist/components/groups/scoped.js.map +1 -0
  115. package/dist/components/media-folder-editor.d.ts +5 -0
  116. package/dist/components/media-folder-editor.js +418 -230
  117. package/dist/components/media-folder-editor.js.map +1 -1
  118. package/dist/components/sortable-list.d.ts +5 -1
  119. package/dist/components/sortable-list.js +97 -81
  120. package/dist/components/sortable-list.js.map +1 -1
  121. package/dist/index.d.ts +1 -1
  122. package/dist/index.js +41 -37
  123. package/dist/locales/admin/de.js +78 -45
  124. package/dist/locales/admin/de.js.map +1 -1
  125. package/dist/locales/admin/en.d.ts +74 -41
  126. package/dist/locales/admin/en.js +78 -45
  127. package/dist/locales/admin/en.js.map +1 -1
  128. package/dist/locales/admin/es.js +78 -45
  129. package/dist/locales/admin/es.js.map +1 -1
  130. package/dist/locales/admin/ja.js +78 -45
  131. package/dist/locales/admin/ja.js.map +1 -1
  132. package/dist/locales/admin/ko.js +78 -45
  133. package/dist/locales/admin/ko.js.map +1 -1
  134. package/dist/locales/admin/zh.js +78 -45
  135. package/dist/locales/admin/zh.js.map +1 -1
  136. package/dist/locales/de.js +1 -0
  137. package/dist/locales/de.js.map +1 -1
  138. package/dist/locales/discovery/de.js +25 -1
  139. package/dist/locales/discovery/de.js.map +1 -1
  140. package/dist/locales/discovery/en.d.ts +24 -0
  141. package/dist/locales/discovery/en.js +25 -1
  142. package/dist/locales/discovery/en.js.map +1 -1
  143. package/dist/locales/discovery/es.js +25 -1
  144. package/dist/locales/discovery/es.js.map +1 -1
  145. package/dist/locales/discovery/ja.js +25 -1
  146. package/dist/locales/discovery/ja.js.map +1 -1
  147. package/dist/locales/discovery/ko.js +25 -1
  148. package/dist/locales/discovery/ko.js.map +1 -1
  149. package/dist/locales/discovery/zh.js +25 -1
  150. package/dist/locales/discovery/zh.js.map +1 -1
  151. package/dist/locales/en.d.ts +119 -43
  152. package/dist/locales/en.js +1 -0
  153. package/dist/locales/en.js.map +1 -1
  154. package/dist/locales/es.js +1 -0
  155. package/dist/locales/es.js.map +1 -1
  156. package/dist/locales/groups/de.js +22 -4
  157. package/dist/locales/groups/de.js.map +1 -1
  158. package/dist/locales/groups/en.d.ts +20 -2
  159. package/dist/locales/groups/en.js +22 -4
  160. package/dist/locales/groups/en.js.map +1 -1
  161. package/dist/locales/groups/es.js +22 -4
  162. package/dist/locales/groups/es.js.map +1 -1
  163. package/dist/locales/groups/ja.js +22 -4
  164. package/dist/locales/groups/ja.js.map +1 -1
  165. package/dist/locales/groups/ko.js +22 -4
  166. package/dist/locales/groups/ko.js.map +1 -1
  167. package/dist/locales/groups/zh.js +22 -4
  168. package/dist/locales/groups/zh.js.map +1 -1
  169. package/dist/locales/ja.js +1 -0
  170. package/dist/locales/ja.js.map +1 -1
  171. package/dist/locales/ko.js +1 -0
  172. package/dist/locales/ko.js.map +1 -1
  173. package/dist/locales/zh.js +1 -0
  174. package/dist/locales/zh.js.map +1 -1
  175. package/dist/react/discovery.d.ts +16 -0
  176. package/dist/react/discovery.js +69 -37
  177. package/dist/react/discovery.js.map +1 -1
  178. package/dist/react/groups.d.ts +19 -3
  179. package/dist/react/groups.js +49 -22
  180. package/dist/react/groups.js.map +1 -1
  181. package/dist/react/index.d.ts +6 -4
  182. package/dist/react/page-notices.d.ts +13 -0
  183. package/dist/react/page-notices.js +38 -0
  184. package/dist/react/page-notices.js.map +1 -0
  185. package/dist/react/post-reads.d.ts +23 -0
  186. package/dist/react/post-reads.js +90 -0
  187. package/dist/react/post-reads.js.map +1 -0
  188. package/dist/react/remembered-sort.d.ts +5 -0
  189. package/dist/react/remembered-sort.js +29 -0
  190. package/dist/react/remembered-sort.js.map +1 -0
  191. package/dist/react/resources.js +2 -2
  192. package/dist/react/resources.js.map +1 -1
  193. package/dist/react/stats.d.ts +3 -7
  194. package/dist/react/stats.js +2 -6
  195. package/dist/react/stats.js.map +1 -1
  196. package/dist/react/use-engagement.d.ts +2 -0
  197. package/dist/react/use-engagement.js +8 -3
  198. package/dist/react/use-engagement.js.map +1 -1
  199. package/dist/react.js +29 -27
  200. package/dist/styles.css +1 -1
  201. package/dist/urls/index.d.ts +1 -1
  202. package/dist/urls.js +2 -2
  203. package/dist/urls.js.map +1 -1
  204. package/package.json +1 -1
  205. package/dist/components/admin/page-review.d.ts +0 -13
  206. package/dist/components/admin/page-review.js +0 -225
  207. package/dist/components/admin/page-review.js.map +0 -1
  208. package/dist/react/page-review.d.ts +0 -14
  209. package/dist/react/page-review.js +0 -37
  210. package/dist/react/page-review.js.map +0 -1
@@ -0,0 +1,382 @@
1
+ import { useMessages as e } from "../../i18n/context.js";
2
+ import { useContentKitClient as t } from "../../react/context.js";
3
+ import { Button as n } from "../../ui/button.js";
4
+ import { Badge as r } from "../../ui/badge.js";
5
+ import { Input as i } from "../../ui/input.js";
6
+ import { Label as a } from "../../ui/label.js";
7
+ import { Select as o, SelectContent as s, SelectItem as c, SelectTrigger as l, SelectValue as u } from "../../ui/select.js";
8
+ import { ErrorLine as d } from "../social/parts.js";
9
+ import { fromLocalInput as f, toLocalInput as p } from "../../client/group-fields.js";
10
+ import { useTypeahead as m } from "../../react/discovery.js";
11
+ import { labelOf as h } from "./parts.js";
12
+ import { useEffect as g, useId as _, useMemo as v, useRef as y, useState as b } from "react";
13
+ import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
14
+ import { cn as w } from "cn";
15
+ import { Cancel01Icon as T } from "@hugeicons/core-free-icons";
16
+ import { HugeiconsIcon as E } from "@hugeicons/react";
17
+ //#region src/components/groups/entity-chips.tsx
18
+ var D = (e) => e.normalize("NFKD").replace(/\p{M}/gu, "").toLocaleLowerCase().replace(/\s+/g, " ").trim();
19
+ function O(e, t, n) {
20
+ let r = t.filter((e) => e.kind === n), i = D(e);
21
+ return r.find((e) => D(e.name) === i) ?? r.find((e) => D(e.slug) === i) ?? (r.length === 1 ? r[0] : void 0);
22
+ }
23
+ function k(n) {
24
+ let { t: r } = e(), i = _(), a = t(n.client), o = y(null), [s, c] = b(""), [l, u] = b([]), [f, p] = b([]), x = n.created ?? [], k = !!n.spec.creatable && !!n.onCreatedChange, A = y(x);
25
+ A.current = x;
26
+ let M = (e) => {
27
+ A.current = e, n.onCreatedChange?.(e);
28
+ }, [N, P] = b(null), [F, I] = b(0), L = s.trim(), R = m(L, {
29
+ entity_kinds: [n.kind],
30
+ display_language: n.language,
31
+ limit: 8,
32
+ client: n.client,
33
+ management: n.management
34
+ }), z = (e) => {
35
+ let t = n.cards.get(e.group_id ?? "");
36
+ return t ? t.name || t.slug : e.group_id ?? "";
37
+ }, B = v(() => new Set(n.memberships.filter((e) => !e.version_id && !e.role).map((e) => e.group_id)), [n.memberships]), V = v(() => R.entities.filter((e) => e.kind === n.kind && !B.has(e.id)).slice(0, 6), [
38
+ R.entities,
39
+ n.kind,
40
+ B
41
+ ]), H = L !== "" && V.length > 0;
42
+ g(() => I(0), [L]);
43
+ let U = (e) => !!n.spec.version_level || !!n.spec.roles?.length || !!n.spec.ordered || e.state === "proposed" || !!e.active_from || !!e.active_until, W = (e) => !B.has(e.id) && (n.onAdd(e), !0), G = (e) => n.management ? a.entities.manage({
44
+ q: e,
45
+ kind: n.kind,
46
+ language: n.language,
47
+ limit: 10
48
+ }).then((e) => e.entities) : a.discovery.typeahead({
49
+ q: e,
50
+ entity_kinds: [n.kind],
51
+ display_language: n.language,
52
+ limit: 10
53
+ }).then((e) => e.entities), K = (e) => {
54
+ let t = /* @__PURE__ */ new Set([
55
+ ...n.memberships.map((e) => D(z(e))),
56
+ ...l.map(D),
57
+ ...f.map(D),
58
+ ...x.map(D)
59
+ ]), r = [];
60
+ for (let n of e) t.has(D(n)) || (t.add(D(n)), r.push(n));
61
+ if (r.length) {
62
+ u((e) => [...e, ...r]);
63
+ for (let e of r) G(e).then((t) => {
64
+ let r = O(e, t, n.kind);
65
+ r ? W(r) : k ? M([...A.current, e]) : p((t) => [...t, e]);
66
+ }, () => p((t) => [...t, e])).finally(() => u((t) => t.filter((t) => t !== e)));
67
+ }
68
+ }, q = (e) => {
69
+ if (!/[,\n]/.test(e)) return c(e);
70
+ let t = e.split(/[,\n]/);
71
+ c(t.pop() ?? ""), K(t.map((e) => e.trim()).filter(Boolean));
72
+ }, J = (e) => {
73
+ c(""), W(e) && (n.spec.version_level || n.spec.roles?.length || n.spec.ordered) && P(n.memberships.length);
74
+ }, Y = () => {
75
+ if (f.length) return p((e) => e.slice(0, -1));
76
+ if (x.length) return M(x.slice(0, -1));
77
+ n.memberships.length && n.onRemove(n.memberships.length - 1);
78
+ }, X = N === null ? void 0 : n.memberships[N];
79
+ return /* @__PURE__ */ C("div", {
80
+ className: "grid min-w-0 gap-1.5",
81
+ "data-ckui": "entity-chips",
82
+ "data-group-kind": n.kind,
83
+ children: [
84
+ /* @__PURE__ */ S("label", {
85
+ htmlFor: `${i}-input`,
86
+ className: "font-semibold",
87
+ children: n.label
88
+ }),
89
+ /* @__PURE__ */ C("div", {
90
+ className: w("relative flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2 py-1.5 focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50", n.disabled && "pointer-events-none opacity-50"),
91
+ onClick: () => o.current?.focus(),
92
+ children: [
93
+ /* @__PURE__ */ C("ul", {
94
+ className: "contents",
95
+ "aria-label": n.label,
96
+ children: [
97
+ n.memberships.map((e, t) => {
98
+ let i = z(e), a = [
99
+ e.role && h(n.labels, e.role),
100
+ e.version_id && n.versionLabel(e.version_id),
101
+ e.position != null && `#${e.position}`
102
+ ].filter(Boolean).join(" · ");
103
+ return /* @__PURE__ */ C("li", {
104
+ className: w("inline-flex max-w-full items-center gap-1 rounded-md bg-muted py-0.5 ps-2 pe-1 text-sm", e.state === "proposed" && "border border-dashed border-primary", N === t && "ring-2 ring-ring"),
105
+ "data-ckui": "entity-chip",
106
+ "data-group": n.cards.get(e.group_id ?? "")?.slug,
107
+ children: [U(e) ? /* @__PURE__ */ C("button", {
108
+ type: "button",
109
+ className: "min-w-0 truncate text-start hover:underline",
110
+ "aria-expanded": N === t,
111
+ "aria-label": r("memberships.chipDetails", { name: i }),
112
+ onClick: (e) => (e.stopPropagation(), P(N === t ? null : t)),
113
+ children: [
114
+ i,
115
+ a && /* @__PURE__ */ C("span", {
116
+ className: "text-muted-foreground",
117
+ children: [" · ", a]
118
+ }),
119
+ e.state === "proposed" && /* @__PURE__ */ C("span", {
120
+ className: "text-primary",
121
+ children: [" · ", r("memberships.proposed")]
122
+ })
123
+ ]
124
+ }) : /* @__PURE__ */ S("span", {
125
+ className: "min-w-0 truncate",
126
+ children: i
127
+ }), /* @__PURE__ */ S("button", {
128
+ type: "button",
129
+ className: "rounded-sm p-0.5 text-muted-foreground hover:bg-background hover:text-foreground",
130
+ "aria-label": r("memberships.remove", { name: i }),
131
+ onClick: (e) => (e.stopPropagation(), N === t && P(null), n.onRemove(t)),
132
+ children: /* @__PURE__ */ S(E, {
133
+ icon: T,
134
+ className: "size-3",
135
+ strokeWidth: 2.5
136
+ })
137
+ })]
138
+ }, `${e.group_id}:${t}`);
139
+ }),
140
+ l.map((e) => /* @__PURE__ */ S("li", {
141
+ className: "inline-flex items-center rounded-md bg-muted px-2 py-0.5 text-sm opacity-60",
142
+ "aria-busy": !0,
143
+ children: e
144
+ }, `pending:${e}`)),
145
+ x.map((e, t) => /* @__PURE__ */ C("li", {
146
+ className: w("inline-flex items-center gap-1 rounded-md py-0.5 ps-2 pe-1 text-sm", n.needsScope ? "border border-dashed border-destructive text-muted-foreground" : "bg-destructive/15 text-destructive"),
147
+ "data-ckui": "entity-chip-new",
148
+ "data-needs-scope": n.needsScope ? "" : void 0,
149
+ children: [/* @__PURE__ */ S("span", {
150
+ className: "min-w-0 truncate",
151
+ title: r("memberships.newChip", { name: e }),
152
+ children: e
153
+ }), /* @__PURE__ */ S("button", {
154
+ type: "button",
155
+ className: "rounded-sm p-0.5 hover:bg-destructive/15",
156
+ "aria-label": r("memberships.remove", { name: e }),
157
+ onClick: (e) => (e.stopPropagation(), M(x.filter((e, n) => n !== t))),
158
+ children: /* @__PURE__ */ S(E, {
159
+ icon: T,
160
+ className: "size-3",
161
+ strokeWidth: 2.5
162
+ })
163
+ })]
164
+ }, `new:${e}`)),
165
+ f.map((e, t) => /* @__PURE__ */ C("li", {
166
+ className: "inline-flex items-center gap-1 rounded-md border border-dashed border-destructive py-0.5 ps-2 pe-1 text-sm text-destructive",
167
+ "data-ckui": "entity-chip-missing",
168
+ children: [/* @__PURE__ */ S("span", {
169
+ className: "line-through",
170
+ children: e
171
+ }), /* @__PURE__ */ S("button", {
172
+ type: "button",
173
+ className: "rounded-sm p-0.5 hover:bg-destructive/15",
174
+ "aria-label": r("memberships.remove", { name: e }),
175
+ onClick: (e) => (e.stopPropagation(), p((e) => e.filter((e, n) => n !== t))),
176
+ children: /* @__PURE__ */ S(E, {
177
+ icon: T,
178
+ className: "size-3",
179
+ strokeWidth: 2.5
180
+ })
181
+ })]
182
+ }, `missing:${e}`))
183
+ ]
184
+ }),
185
+ /* @__PURE__ */ S("input", {
186
+ ref: o,
187
+ id: `${i}-input`,
188
+ role: "combobox",
189
+ "aria-label": r("memberships.add", { kind: n.label }),
190
+ "aria-expanded": H,
191
+ "aria-controls": `${i}-list`,
192
+ "aria-activedescendant": H ? `${i}-${F}` : void 0,
193
+ "aria-autocomplete": "list",
194
+ autoComplete: "off",
195
+ disabled: n.disabled,
196
+ className: "min-w-32 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground",
197
+ placeholder: n.memberships.length || f.length || x.length ? "" : r("memberships.chipsPlaceholder"),
198
+ value: s,
199
+ onChange: (e) => q(e.target.value),
200
+ onBlur: () => {
201
+ L && K([L]), c("");
202
+ },
203
+ onKeyDown: (e) => {
204
+ e.key === "Backspace" && s === "" ? (e.preventDefault(), Y()) : e.key === "ArrowDown" && H ? (e.preventDefault(), I((e) => Math.min(V.length - 1, e + 1))) : e.key === "ArrowUp" && H ? (e.preventDefault(), I((e) => Math.max(0, e - 1))) : e.key === "Enter" ? (e.preventDefault(), H ? J(V[F]) : L && (K([L]), c(""))) : e.key === "Escape" && c("");
205
+ }
206
+ }),
207
+ H && /* @__PURE__ */ S("ul", {
208
+ id: `${i}-list`,
209
+ role: "listbox",
210
+ "aria-label": n.label,
211
+ className: "absolute start-0 top-full z-10 mt-1 grid w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md",
212
+ children: V.map((e, t) => /* @__PURE__ */ C("li", {
213
+ id: `${i}-${t}`,
214
+ role: "option",
215
+ "aria-selected": t === F,
216
+ className: w("flex cursor-pointer items-baseline justify-between gap-2 px-3 py-1.5 text-sm", t === F && "bg-accent text-accent-foreground"),
217
+ onMouseEnter: () => I(t),
218
+ onMouseDown: (t) => {
219
+ t.preventDefault(), J(e);
220
+ },
221
+ children: [/* @__PURE__ */ S("span", {
222
+ className: "min-w-0 truncate",
223
+ children: e.name || e.slug
224
+ }), /* @__PURE__ */ S("span", {
225
+ className: "text-xs text-muted-foreground",
226
+ children: e.slug
227
+ })]
228
+ }, e.id))
229
+ })
230
+ ]
231
+ }),
232
+ x.length > 0 && /* @__PURE__ */ S("p", {
233
+ className: "text-xs text-muted-foreground",
234
+ children: n.needsScope ? r("memberships.needsScope", { scope: n.needsScope }) : r("memberships.newHint")
235
+ }),
236
+ f.length > 0 && /* @__PURE__ */ S("p", {
237
+ className: "text-xs text-destructive",
238
+ role: "status",
239
+ children: r("memberships.notFound", { names: f.join(", ") })
240
+ }),
241
+ /* @__PURE__ */ S(d, { error: R.error }),
242
+ X && N !== null && /* @__PURE__ */ S("ul", { children: /* @__PURE__ */ S(j, {
243
+ m: X,
244
+ card: n.cards.get(X.group_id ?? ""),
245
+ spec: n.spec,
246
+ labels: n.labels,
247
+ versions: n.versions,
248
+ versionLabel: n.versionLabel,
249
+ onChange: (e) => n.onChange(N, e),
250
+ onRemove: () => {
251
+ P(null), n.onRemove(N);
252
+ }
253
+ }) })
254
+ ]
255
+ });
256
+ }
257
+ var A = "__none__";
258
+ function j({ m: t, card: d, spec: f, labels: p, versions: m, versionLabel: g, onChange: v, onRemove: y }) {
259
+ let { t: b } = e(), w = _(), T = d ? d.name || d.slug : t.group_id ?? "", E = [.../* @__PURE__ */ new Set([...(m ?? []).map((e) => e.id), ...t.version_id ? [t.version_id] : []])];
260
+ return /* @__PURE__ */ C("li", {
261
+ className: "flex flex-wrap items-center gap-2 rounded-md border border-border p-2",
262
+ "data-ckui": "membership",
263
+ "data-group": d?.slug,
264
+ "data-state": t.state ?? "active",
265
+ children: [
266
+ /* @__PURE__ */ S("span", {
267
+ className: "min-w-0 flex-1 font-medium break-words",
268
+ children: T
269
+ }),
270
+ t.state === "proposed" && /* @__PURE__ */ C(x, { children: [/* @__PURE__ */ S(r, {
271
+ variant: "secondary",
272
+ children: b("memberships.proposed")
273
+ }), /* @__PURE__ */ S(n, {
274
+ type: "button",
275
+ size: "xs",
276
+ variant: "outline",
277
+ onClick: () => v({ state: "active" }),
278
+ children: b("memberships.accept")
279
+ })] }),
280
+ f.version_level && E.length > 0 && /* @__PURE__ */ C(o, {
281
+ value: t.version_id ?? A,
282
+ onValueChange: (e) => v({ version_id: e === A ? void 0 : String(e) }),
283
+ children: [/* @__PURE__ */ S(l, {
284
+ size: "sm",
285
+ "aria-label": b("memberships.versionOf", { name: T }),
286
+ children: /* @__PURE__ */ S(u, { children: (e) => e === A ? b("memberships.wholeContent") : g(e) })
287
+ }), /* @__PURE__ */ C(s, { children: [/* @__PURE__ */ S(c, {
288
+ value: A,
289
+ children: b("memberships.wholeContent")
290
+ }), E.map((e) => /* @__PURE__ */ S(c, {
291
+ value: e,
292
+ children: g(e)
293
+ }, e))] })]
294
+ }),
295
+ !!f.roles?.length && /* @__PURE__ */ C(o, {
296
+ value: t.role || A,
297
+ onValueChange: (e) => v({ role: e === A ? void 0 : String(e) }),
298
+ children: [/* @__PURE__ */ S(l, {
299
+ size: "sm",
300
+ "aria-label": b("memberships.roleOf", { name: T }),
301
+ children: /* @__PURE__ */ S(u, { children: (e) => e === A ? b("memberships.noRole") : h(p, e) })
302
+ }), /* @__PURE__ */ C(s, { children: [/* @__PURE__ */ S(c, {
303
+ value: A,
304
+ children: b("memberships.noRole")
305
+ }), f.roles.map((e) => /* @__PURE__ */ S(c, {
306
+ value: e,
307
+ children: h(p, e)
308
+ }, e))] })]
309
+ }),
310
+ f.ordered && /* @__PURE__ */ C("div", {
311
+ className: "flex items-center gap-1",
312
+ children: [/* @__PURE__ */ S(a, {
313
+ htmlFor: `${w}-pos`,
314
+ className: "text-xs text-muted-foreground",
315
+ children: b("memberships.position")
316
+ }), /* @__PURE__ */ S(i, {
317
+ id: `${w}-pos`,
318
+ className: "h-8 w-20",
319
+ type: "number",
320
+ min: 0,
321
+ step: 1,
322
+ value: t.position ?? "",
323
+ placeholder: b("memberships.last"),
324
+ onChange: (e) => v({ position: e.target.value === "" ? void 0 : Math.max(0, Math.trunc(Number(e.target.value))) })
325
+ })]
326
+ }),
327
+ f.windows && /* @__PURE__ */ S(M, {
328
+ from: t.active_from,
329
+ until: t.active_until,
330
+ name: T,
331
+ onChange: v
332
+ }),
333
+ /* @__PURE__ */ S(n, {
334
+ type: "button",
335
+ size: "xs",
336
+ variant: "ghost",
337
+ "aria-label": b("memberships.remove", { name: T }),
338
+ onClick: y,
339
+ children: b("common.remove")
340
+ })
341
+ ]
342
+ });
343
+ }
344
+ function M({ from: t, until: n, name: r, onChange: o }) {
345
+ let { t: s } = e(), c = _();
346
+ return /* @__PURE__ */ C("div", {
347
+ className: "flex flex-wrap items-center gap-1",
348
+ "data-ckui": "membership-window",
349
+ children: [
350
+ /* @__PURE__ */ S(a, {
351
+ htmlFor: `${c}-from`,
352
+ className: "text-xs text-muted-foreground",
353
+ children: s("memberships.from")
354
+ }),
355
+ /* @__PURE__ */ S(i, {
356
+ id: `${c}-from`,
357
+ className: "h-8 w-48",
358
+ type: "datetime-local",
359
+ "aria-label": s("memberships.fromOf", { name: r }),
360
+ value: p(t),
361
+ onChange: (e) => o({ active_from: f(e.target.value) })
362
+ }),
363
+ /* @__PURE__ */ S(a, {
364
+ htmlFor: `${c}-until`,
365
+ className: "text-xs text-muted-foreground",
366
+ children: s("memberships.until")
367
+ }),
368
+ /* @__PURE__ */ S(i, {
369
+ id: `${c}-until`,
370
+ className: "h-8 w-48",
371
+ type: "datetime-local",
372
+ "aria-label": s("memberships.untilOf", { name: r }),
373
+ value: p(n),
374
+ onChange: (e) => o({ active_until: f(e.target.value) })
375
+ })
376
+ ]
377
+ });
378
+ }
379
+ //#endregion
380
+ export { k as EntityChips, j as MembershipRow, M as WindowFields, O as resolveToken };
381
+
382
+ //# sourceMappingURL=entity-chips.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-chips.js","names":[],"sources":["../../../src/components/groups/entity-chips.tsx"],"sourcesContent":["import { Cancel01Icon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { fromLocalInput, toLocalInput } from \"../../client/group-fields.js\";\nimport type { GroupCard, GroupKind, Membership } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { useContentKitClient } from \"../../react/context.js\";\nimport { useTypeahead } from \"../../react/discovery.js\";\nimport { ErrorLine } from \"../social/parts.js\";\nimport { Badge } from \"#ckui/ui/badge\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Input } from \"#ckui/ui/input\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"#ckui/ui/select\";\nimport { labelOf, type Labels } from \"./parts.js\";\n\nexport interface EntityChipsProps {\n /** The entity kind these links join. */\n kind: string;\n label: string;\n /** This kind's memberships, in order; callbacks index into this list. */\n memberships: readonly Membership[];\n cards: ReadonlyMap<string, GroupCard>;\n spec: GroupKind;\n labels?: Labels;\n versions?: readonly VersionChoice[];\n versionLabel: (id: string) => string;\n language?: string;\n /** Staff lookup, including internal entities. */\n management?: boolean;\n client?: ContentKitClient;\n disabled?: boolean;\n /** Names no entity carries yet, created on save (kinds with spec.creatable). */\n created?: readonly string[];\n onCreatedChange?: (names: string[]) => void;\n /** A scoped kind's new names wait for exactly one entity of this scope (its label). */\n needsScope?: string;\n onAdd: (card: GroupCard) => void;\n onChange: (index: number, patch: Partial<Membership>) => void;\n onRemove: (index: number) => void;\n}\n\nconst fold = (s: string) =>\n s\n .normalize(\"NFKD\")\n .replace(/\\p{M}/gu, \"\")\n .toLocaleLowerCase()\n .replace(/\\s+/g, \" \")\n .trim();\n\n/** Splits typed or pasted text on commas and newlines into trimmed tokens. */\nexport function splitTokens(text: string): string[] {\n return text\n .split(/[,\\n]/)\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/** An exact name or slug match wins; a lone result is an alias match. */\nexport function resolveToken(token: string, found: readonly GroupCard[], kind: string): GroupCard | undefined {\n const own = found.filter((g) => g.kind === kind);\n const key = fold(token);\n return own.find((g) => fold(g.name) === key) ?? own.find((g) => fold(g.slug) === key) ?? (own.length === 1 ? own[0] : undefined);\n}\n\n/**\n * A content's links to one entity kind as chips: type or paste names\n * separated by commas, remove with × or Backspace. A chip with roles,\n * versions, positions or a proposal opens those details. A name without a\n * match is new, created on save, where the kind is creatable; elsewhere it\n * stays marked and is not saved.\n */\nexport function EntityChips(p: EntityChipsProps) {\n const { t } = useMessages();\n const id = useId();\n const client = useContentKitClient(p.client);\n const input = useRef<HTMLInputElement>(null);\n const [text, setText] = useState(\"\");\n const [pending, setPending] = useState<string[]>([]);\n const [missing, setMissing] = useState<string[]>([]);\n const created = p.created ?? [];\n const creatable = !!p.spec.creatable && !!p.onCreatedChange;\n // Lookups settle out of order; each appends to the latest list.\n const latestCreated = useRef(created);\n latestCreated.current = created;\n const setCreated = (names: string[]) => {\n latestCreated.current = names;\n p.onCreatedChange?.(names);\n };\n const [open, setOpen] = useState<number | null>(null);\n const [active, setActive] = useState(0);\n const fragment = text.trim();\n const found = useTypeahead(fragment, { entity_kinds: [p.kind], display_language: p.language, limit: 8, client: p.client, management: p.management });\n const name = (m: Membership) => {\n const card = p.cards.get(m.group_id ?? \"\");\n return card ? card.name || card.slug : (m.group_id ?? \"\");\n };\n // A whole-content link without a role is the one duplicate to skip.\n const plain = useMemo(() => new Set(p.memberships.filter((m) => !m.version_id && !m.role).map((m) => m.group_id)), [p.memberships]);\n const suggestions = useMemo(() => found.entities.filter((g) => g.kind === p.kind && !plain.has(g.id)).slice(0, 6), [found.entities, p.kind, plain]);\n const listOpen = fragment !== \"\" && suggestions.length > 0;\n useEffect(() => setActive(0), [fragment]);\n const detailed = (m: Membership) => !!p.spec.version_level || !!p.spec.roles?.length || !!p.spec.ordered || m.state === \"proposed\" || !!m.active_from || !!m.active_until;\n const add = (card: GroupCard) => {\n if (plain.has(card.id)) return false;\n p.onAdd(card);\n return true;\n };\n const lookup = (token: string) =>\n p.management\n ? client.entities.manage({ q: token, kind: p.kind, language: p.language, limit: 10 }).then((page) => page.entities)\n : client.discovery.typeahead({ q: token, entity_kinds: [p.kind], display_language: p.language, limit: 10 }).then((r) => r.entities);\n const commit = (tokens: string[]) => {\n const known = new Set([...p.memberships.map((m) => fold(name(m))), ...pending.map(fold), ...missing.map(fold), ...created.map(fold)]);\n const fresh: string[] = [];\n for (const token of tokens) {\n if (known.has(fold(token))) continue;\n known.add(fold(token));\n fresh.push(token);\n }\n if (!fresh.length) return;\n setPending((all) => [...all, ...fresh]);\n for (const token of fresh) {\n lookup(token).then(\n (cards) => {\n const card = resolveToken(token, cards, p.kind);\n if (card) add(card);\n else if (creatable) setCreated([...latestCreated.current, token]);\n else setMissing((all) => [...all, token]);\n },\n () => setMissing((all) => [...all, token]),\n ).finally(() => setPending((all) => all.filter((x) => x !== token)));\n }\n };\n const type = (value: string) => {\n if (!/[,\\n]/.test(value)) return setText(value);\n const parts = value.split(/[,\\n]/);\n setText(parts.pop() ?? \"\");\n commit(parts.map((s) => s.trim()).filter(Boolean));\n };\n // One picked name with roles, versions or positions opens its details.\n const pick = (card: GroupCard) => {\n setText(\"\");\n if (add(card) && (p.spec.version_level || p.spec.roles?.length || p.spec.ordered)) setOpen(p.memberships.length);\n };\n const removeLast = () => {\n if (missing.length) return setMissing((all) => all.slice(0, -1));\n if (created.length) return setCreated(created.slice(0, -1));\n if (p.memberships.length) p.onRemove(p.memberships.length - 1);\n };\n const detail = open !== null ? p.memberships[open] : undefined;\n return (\n <div className=\"grid min-w-0 gap-1.5\" data-ckui=\"entity-chips\" data-group-kind={p.kind}>\n <label htmlFor={`${id}-input`} className=\"font-semibold\">\n {p.label}\n </label>\n <div\n className={cn(\n \"relative flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2 py-1.5 focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50\",\n p.disabled && \"pointer-events-none opacity-50\",\n )}\n onClick={() => input.current?.focus()}\n >\n <ul className=\"contents\" aria-label={p.label}>\n {p.memberships.map((m, i) => {\n const n = name(m);\n const extra = [m.role && labelOf(p.labels, m.role), m.version_id && p.versionLabel(m.version_id), m.position != null && `#${m.position}`].filter(Boolean).join(\" · \");\n return (\n <li key={`${m.group_id}:${i}`} className={cn(\"inline-flex max-w-full items-center gap-1 rounded-md bg-muted py-0.5 ps-2 pe-1 text-sm\", m.state === \"proposed\" && \"border border-dashed border-primary\", open === i && \"ring-2 ring-ring\")} data-ckui=\"entity-chip\" data-group={p.cards.get(m.group_id ?? \"\")?.slug}>\n {detailed(m) ? (\n <button type=\"button\" className=\"min-w-0 truncate text-start hover:underline\" aria-expanded={open === i} aria-label={t(\"memberships.chipDetails\", { name: n })} onClick={(e) => (e.stopPropagation(), setOpen(open === i ? null : i))}>\n {n}\n {extra && <span className=\"text-muted-foreground\"> · {extra}</span>}\n {m.state === \"proposed\" && <span className=\"text-primary\"> · {t(\"memberships.proposed\")}</span>}\n </button>\n ) : (\n <span className=\"min-w-0 truncate\">{n}</span>\n )}\n <button type=\"button\" className=\"rounded-sm p-0.5 text-muted-foreground hover:bg-background hover:text-foreground\" aria-label={t(\"memberships.remove\", { name: n })} onClick={(e) => (e.stopPropagation(), open === i && setOpen(null), p.onRemove(i))}>\n <HugeiconsIcon icon={Cancel01Icon} className=\"size-3\" strokeWidth={2.5} />\n </button>\n </li>\n );\n })}\n {pending.map((token) => (\n <li key={`pending:${token}`} className=\"inline-flex items-center rounded-md bg-muted px-2 py-0.5 text-sm opacity-60\" aria-busy>\n {token}\n </li>\n ))}\n {created.map((token, i) => (\n <li\n key={`new:${token}`}\n className={cn(\"inline-flex items-center gap-1 rounded-md py-0.5 ps-2 pe-1 text-sm\", p.needsScope ? \"border border-dashed border-destructive text-muted-foreground\" : \"bg-destructive/15 text-destructive\")}\n data-ckui=\"entity-chip-new\"\n data-needs-scope={p.needsScope ? \"\" : undefined}\n >\n <span className=\"min-w-0 truncate\" title={t(\"memberships.newChip\", { name: token })}>\n {token}\n </span>\n <button type=\"button\" className=\"rounded-sm p-0.5 hover:bg-destructive/15\" aria-label={t(\"memberships.remove\", { name: token })} onClick={(e) => (e.stopPropagation(), setCreated(created.filter((_, j) => j !== i)))}>\n <HugeiconsIcon icon={Cancel01Icon} className=\"size-3\" strokeWidth={2.5} />\n </button>\n </li>\n ))}\n {missing.map((token, i) => (\n <li key={`missing:${token}`} className=\"inline-flex items-center gap-1 rounded-md border border-dashed border-destructive py-0.5 ps-2 pe-1 text-sm text-destructive\" data-ckui=\"entity-chip-missing\">\n <span className=\"line-through\">{token}</span>\n <button type=\"button\" className=\"rounded-sm p-0.5 hover:bg-destructive/15\" aria-label={t(\"memberships.remove\", { name: token })} onClick={(e) => (e.stopPropagation(), setMissing((all) => all.filter((_, j) => j !== i)))}>\n <HugeiconsIcon icon={Cancel01Icon} className=\"size-3\" strokeWidth={2.5} />\n </button>\n </li>\n ))}\n </ul>\n <input\n ref={input}\n id={`${id}-input`}\n role=\"combobox\"\n aria-label={t(\"memberships.add\", { kind: p.label })}\n aria-expanded={listOpen}\n aria-controls={`${id}-list`}\n aria-activedescendant={listOpen ? `${id}-${active}` : undefined}\n aria-autocomplete=\"list\"\n autoComplete=\"off\"\n disabled={p.disabled}\n className=\"min-w-32 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground\"\n placeholder={p.memberships.length || missing.length || created.length ? \"\" : t(\"memberships.chipsPlaceholder\")}\n value={text}\n onChange={(e) => type(e.target.value)}\n onBlur={() => {\n if (fragment) commit([fragment]);\n setText(\"\");\n }}\n onKeyDown={(e) => {\n if (e.key === \"Backspace\" && text === \"\") {\n e.preventDefault();\n removeLast();\n } else if (e.key === \"ArrowDown\" && listOpen) {\n e.preventDefault();\n setActive((a) => Math.min(suggestions.length - 1, a + 1));\n } else if (e.key === \"ArrowUp\" && listOpen) {\n e.preventDefault();\n setActive((a) => Math.max(0, a - 1));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n if (listOpen) pick(suggestions[active]!);\n else if (fragment) {\n commit([fragment]);\n setText(\"\");\n }\n } else if (e.key === \"Escape\") setText(\"\");\n }}\n />\n {listOpen && (\n <ul id={`${id}-list`} role=\"listbox\" aria-label={p.label} className=\"absolute start-0 top-full z-10 mt-1 grid w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md\">\n {suggestions.map((g, i) => (\n <li\n key={g.id}\n id={`${id}-${i}`}\n role=\"option\"\n aria-selected={i === active}\n className={cn(\"flex cursor-pointer items-baseline justify-between gap-2 px-3 py-1.5 text-sm\", i === active && \"bg-accent text-accent-foreground\")}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(g);\n }}\n >\n <span className=\"min-w-0 truncate\">{g.name || g.slug}</span>\n <span className=\"text-xs text-muted-foreground\">{g.slug}</span>\n </li>\n ))}\n </ul>\n )}\n </div>\n {created.length > 0 && <p className=\"text-xs text-muted-foreground\">{p.needsScope ? t(\"memberships.needsScope\", { scope: p.needsScope }) : t(\"memberships.newHint\")}</p>}\n {missing.length > 0 && (\n <p className=\"text-xs text-destructive\" role=\"status\">\n {t(\"memberships.notFound\", { names: missing.join(\", \") })}\n </p>\n )}\n <ErrorLine error={found.error} />\n {detail && open !== null && (\n <ul>\n <MembershipRow\n m={detail}\n card={p.cards.get(detail.group_id ?? \"\")}\n spec={p.spec}\n labels={p.labels}\n versions={p.versions}\n versionLabel={p.versionLabel}\n onChange={(patch) => p.onChange(open, patch)}\n onRemove={() => {\n setOpen(null);\n p.onRemove(open);\n }}\n />\n </ul>\n )}\n </div>\n );\n}\n\nconst NONE = \"__none__\";\n\n/** A version a membership may target. */\nexport interface VersionChoice {\n id: string;\n label: string;\n}\n\nexport function MembershipRow({\n m: x,\n card,\n spec,\n labels,\n versions,\n versionLabel,\n onChange,\n onRemove,\n}: {\n m: Membership;\n card?: GroupCard;\n spec: GroupKind;\n labels?: Labels;\n versions?: readonly VersionChoice[];\n versionLabel: (id: string) => string;\n onChange: (patch: Partial<Membership>) => void;\n onRemove: () => void;\n}) {\n const { t } = useMessages();\n const id = useId();\n const name = card ? card.name || card.slug : (x.group_id ?? \"\");\n const versionIds = [...new Set([...(versions ?? []).map((v) => v.id), ...(x.version_id ? [x.version_id] : [])])];\n return (\n <li className=\"flex flex-wrap items-center gap-2 rounded-md border border-border p-2\" data-ckui=\"membership\" data-group={card?.slug} data-state={x.state ?? \"active\"}>\n <span className=\"min-w-0 flex-1 font-medium break-words\">{name}</span>\n {x.state === \"proposed\" && (\n <>\n <Badge variant=\"secondary\">{t(\"memberships.proposed\")}</Badge>\n <Button type=\"button\" size=\"xs\" variant=\"outline\" onClick={() => onChange({ state: \"active\" })}>\n {t(\"memberships.accept\")}\n </Button>\n </>\n )}\n {spec.version_level && versionIds.length > 0 && (\n <Select value={x.version_id ?? NONE} onValueChange={(v) => onChange({ version_id: v === NONE ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.versionOf\", { name })}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.wholeContent\") : versionLabel(v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.wholeContent\")}</SelectItem>\n {versionIds.map((v) => (\n <SelectItem key={v} value={v}>\n {versionLabel(v)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {!!spec.roles?.length && (\n <Select value={x.role || NONE} onValueChange={(v) => onChange({ role: v === NONE ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.roleOf\", { name })}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.noRole\") : labelOf(labels, v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.noRole\")}</SelectItem>\n {spec.roles.map((r) => (\n <SelectItem key={r} value={r}>\n {labelOf(labels, r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {spec.ordered && (\n <div className=\"flex items-center gap-1\">\n <Label htmlFor={`${id}-pos`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.position\")}\n </Label>\n <Input\n id={`${id}-pos`}\n className=\"h-8 w-20\"\n type=\"number\"\n min={0}\n step={1}\n value={x.position ?? \"\"}\n placeholder={t(\"memberships.last\")}\n onChange={(e) => onChange({ position: e.target.value === \"\" ? undefined : Math.max(0, Math.trunc(Number(e.target.value))) })}\n />\n </div>\n )}\n {spec.windows && <WindowFields from={x.active_from} until={x.active_until} name={name} onChange={onChange} />}\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" aria-label={t(\"memberships.remove\", { name })} onClick={onRemove}>\n {t(\"common.remove\")}\n </Button>\n </li>\n );\n}\n\nexport function WindowFields({ from, until, name, onChange }: { from?: string; until?: string; name: string; onChange: (patch: Partial<Membership>) => void }) {\n const { t } = useMessages();\n const id = useId();\n return (\n <div className=\"flex flex-wrap items-center gap-1\" data-ckui=\"membership-window\">\n <Label htmlFor={`${id}-from`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.from\")}\n </Label>\n <Input\n id={`${id}-from`}\n className=\"h-8 w-48\"\n type=\"datetime-local\"\n aria-label={t(\"memberships.fromOf\", { name })}\n value={toLocalInput(from)}\n onChange={(e) => onChange({ active_from: fromLocalInput(e.target.value) })}\n />\n <Label htmlFor={`${id}-until`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.until\")}\n </Label>\n <Input\n id={`${id}-until`}\n className=\"h-8 w-48\"\n type=\"datetime-local\"\n aria-label={t(\"memberships.untilOf\", { name })}\n value={toLocalInput(until)}\n onChange={(e) => onChange({ active_until: fromLocalInput(e.target.value) })}\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { ReactNode } from 'react';
2
+ import { ContentKitUiAppearance } from '../../appearance.js';
3
+ import { ContentKitClient } from '../../client/client.js';
4
+ import { Content, GroupDetail, Membership } from '../../client/generated/wire.js';
5
+ import { ContentKitErrorHandler } from '../../react/context.js';
6
+ import { Labels } from './parts.js';
7
+ export interface GroupMembersProps {
8
+ group: Pick<GroupDetail, "id" | "kind" | "name" | "slug" | "cover" | "code">;
9
+ labels?: Labels;
10
+ /** Where a member's card links, e.g. its admin editor; none: not a link. */
11
+ contentHref?: (content: Content) => string | undefined;
12
+ /** Where a new item of a content kind starts already in this group, e.g. the host's editor with `?with=<code>`; none: no action. */
13
+ newContentHref?: (contentKind: string, group: GroupMembersProps["group"]) => string | undefined;
14
+ /** Replaces a member's card body; default its cover and title. */
15
+ renderContent?: (member: Membership, content?: Content) => ReactNode;
16
+ /** Select a member's cover as the group's. */
17
+ onUseCover?: (contentId: string) => Promise<unknown>;
18
+ pageSize?: number;
19
+ client?: ContentKitClient;
20
+ onError?: ContentKitErrorHandler;
21
+ className?: string;
22
+ appearance?: ContentKitUiAppearance;
23
+ }
24
+ /**
25
+ * Staff: an entity's contents as cover cards grouped by content kind (an
26
+ * ordered kind as a reorderable list), each with its access, state, role and
27
+ * version; add one by searching titles, remove or use its cover on hover.
28
+ */
29
+ export declare function GroupMembers(p: GroupMembersProps): import('react').JSX.Element;