@openrails/contentkit-ui 0.89.0 → 0.89.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 (43) hide show
  1. package/README.md +29 -2
  2. package/dist/client/browser-search-history.d.ts +24 -0
  3. package/dist/client/browser-search-history.js +92 -0
  4. package/dist/client/browser-search-history.js.map +1 -0
  5. package/dist/client/discovery.d.ts +5 -2
  6. package/dist/client/discovery.js +14 -22
  7. package/dist/client/discovery.js.map +1 -1
  8. package/dist/client/generated/routes.d.ts +3 -3
  9. package/dist/client/generated/routes.js +3 -2
  10. package/dist/client/generated/routes.js.map +1 -1
  11. package/dist/client.js +14 -14
  12. package/dist/components/content/filters.d.ts +1 -1
  13. package/dist/components/content/filters.js +32 -52
  14. package/dist/components/content/filters.js.map +1 -1
  15. package/dist/components/content/index.d.ts +1 -0
  16. package/dist/components/content/reader-settings.d.ts +19 -0
  17. package/dist/components/content/reader-settings.js +95 -0
  18. package/dist/components/content/reader-settings.js.map +1 -0
  19. package/dist/components/content/search.d.ts +2 -0
  20. package/dist/components/content/search.js +334 -137
  21. package/dist/components/content/search.js.map +1 -1
  22. package/dist/index.js +17 -16
  23. package/dist/locales/discovery/de.js +9 -0
  24. package/dist/locales/discovery/de.js.map +1 -1
  25. package/dist/locales/discovery/en.d.ts +9 -0
  26. package/dist/locales/discovery/en.js +9 -0
  27. package/dist/locales/discovery/en.js.map +1 -1
  28. package/dist/locales/discovery/es.js +9 -0
  29. package/dist/locales/discovery/es.js.map +1 -1
  30. package/dist/locales/discovery/ja.js +9 -0
  31. package/dist/locales/discovery/ja.js.map +1 -1
  32. package/dist/locales/discovery/ko.js +9 -0
  33. package/dist/locales/discovery/ko.js.map +1 -1
  34. package/dist/locales/discovery/zh.js +9 -0
  35. package/dist/locales/discovery/zh.js.map +1 -1
  36. package/dist/locales/en.d.ts +9 -0
  37. package/dist/react/discovery.d.ts +1 -1
  38. package/dist/react/discovery.js +145 -92
  39. package/dist/react/discovery.js.map +1 -1
  40. package/dist/styles.css +1 -1
  41. package/dist/ui/dialog.js +16 -10
  42. package/dist/ui/dialog.js.map +1 -1
  43. package/package.json +1 -1
@@ -11,75 +11,55 @@ import { useContext as f, useId as p } from "react";
11
11
  import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
12
12
  import { cn as _ } from "cn";
13
13
  //#region src/components/content/filters.tsx
14
- function v(d) {
15
- let v = e(), { t: y } = v, b = p(), x = f(n), S = u({
16
- language: d.language,
17
- client: d.client
18
- }), C = c("filters.save", d.onError), w = (e) => /* @__PURE__ */ h(t, {
19
- appearance: d.appearance,
20
- className: _("grid gap-3 text-sm", d.className),
14
+ function v(r) {
15
+ let d = e(), { t: v } = d, y = p(), b = f(n), x = u({
16
+ language: r.language,
17
+ client: r.client
18
+ }), S = c("filters.save", r.onError), C = (e) => /* @__PURE__ */ h(t, {
19
+ appearance: r.appearance,
20
+ className: _("grid gap-3 text-sm", r.className),
21
21
  "data-ckui": "content-filters",
22
22
  children: e
23
23
  });
24
- if (x?.viewer === null) return w(/* @__PURE__ */ h("p", {
24
+ if (b?.viewer === null) return C(/* @__PURE__ */ h("p", {
25
25
  className: "text-muted-foreground",
26
- children: y("contents.filtersSignedOut")
26
+ children: v("contents.filtersSignedOut")
27
27
  }));
28
- if (!S.filters) return S.error ? w(/* @__PURE__ */ h(o, { children: s(v, S.error) })) : w(/* @__PURE__ */ h(a, { className: "h-24 w-full" }));
29
- let T = S.filters;
30
- return !T.filters.length && d.includeDeleted === !1 ? null : w(/* @__PURE__ */ g(m, { children: [
31
- T.filters.length ? /* @__PURE__ */ h("ul", {
28
+ if (!x.filters) return x.error ? C(/* @__PURE__ */ h(o, { children: s(d, x.error) })) : C(/* @__PURE__ */ h(a, { className: "h-24 w-full" }));
29
+ let w = x.filters;
30
+ return !w.filters.length && r.includeDeleted === !1 ? null : C(/* @__PURE__ */ g(m, { children: [
31
+ w.filters.length ? /* @__PURE__ */ h("ul", {
32
32
  className: "grid divide-y divide-border rounded-lg border border-border",
33
- children: T.filters.map((e) => /* @__PURE__ */ g("li", {
33
+ children: w.filters.map((e) => /* @__PURE__ */ g("li", {
34
34
  className: "flex flex-wrap items-center gap-3 p-3",
35
35
  "data-ckui": "content-filter",
36
36
  "data-slug": e.group.slug,
37
37
  "data-visible": e.visible,
38
- children: [
39
- /* @__PURE__ */ h(l, {
40
- id: `${b}-${e.group.id}`,
41
- checked: e.visible,
42
- disabled: C.pending,
43
- onCheckedChange: (t) => void C.run(() => S.setVisible(e.group.id, t))
44
- }),
45
- /* @__PURE__ */ h(i, {
46
- htmlFor: `${b}-${e.group.id}`,
47
- className: "min-w-0 flex-1",
48
- children: e.label || e.group.name
49
- }),
50
- /* @__PURE__ */ h("span", {
51
- className: "text-xs text-muted-foreground",
52
- children: y(e.visible ? "contents.shown" : "contents.hidden")
53
- }),
54
- e.overridden && /* @__PURE__ */ h(r, {
55
- size: "xs",
56
- variant: "ghost",
57
- disabled: C.pending,
58
- onClick: () => void C.run(() => S.save({
59
- filters: T.filters.filter((t) => t.overridden && t.group.id !== e.group.id).map((e) => ({
60
- group_id: e.group.id,
61
- visible: e.visible
62
- })),
63
- include_deleted: T.include_deleted
64
- })),
65
- children: y("contents.useDefault")
66
- })
67
- ]
38
+ children: [/* @__PURE__ */ h(l, {
39
+ id: `${y}-${e.group.id}`,
40
+ checked: e.visible,
41
+ disabled: S.pending,
42
+ onCheckedChange: (t) => void S.run(() => x.setVisible(e.group.id, t))
43
+ }), /* @__PURE__ */ h(i, {
44
+ htmlFor: `${y}-${e.group.id}`,
45
+ className: "min-w-0 flex-1",
46
+ children: e.label || e.group.name
47
+ })]
68
48
  }, e.group.id))
69
49
  }) : null,
70
- d.includeDeleted !== !1 && /* @__PURE__ */ g("div", {
50
+ r.includeDeleted !== !1 && /* @__PURE__ */ g("div", {
71
51
  className: "flex items-center gap-3",
72
52
  children: [/* @__PURE__ */ h(l, {
73
- id: `${b}-deleted`,
74
- checked: T.include_deleted,
75
- disabled: C.pending,
76
- onCheckedChange: (e) => void C.run(() => S.setIncludeDeleted(e))
53
+ id: `${y}-deleted`,
54
+ checked: w.include_deleted,
55
+ disabled: S.pending,
56
+ onCheckedChange: (e) => void S.run(() => x.setIncludeDeleted(e))
77
57
  }), /* @__PURE__ */ h(i, {
78
- htmlFor: `${b}-deleted`,
79
- children: y("contents.includeDeleted")
58
+ htmlFor: `${y}-deleted`,
59
+ children: v("contents.includeDeleted")
80
60
  })]
81
61
  }),
82
- /* @__PURE__ */ h(o, { error: C.error })
62
+ /* @__PURE__ */ h(o, { error: S.error })
83
63
  ] }));
84
64
  }
85
65
  function y({ query: n = {}, selected: i, onSelect: c, client: l, className: u, appearance: f }) {
@@ -1 +1 @@
1
- {"version":3,"file":"filters.js","names":[],"sources":["../../../src/components/content/filters.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useContext, useId } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ReleaseDatesQuery } from \"../../client/discovery.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentFilters, useReleaseDates } from \"../../react/discovery.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { Switch } from \"#ckui/ui/switch\";\nimport { contentError, ErrorLine, useAction } from \"../social/parts.js\";\n\nexport interface ContentFilterSettingsProps {\n /** Labels and group names in this language; default the provider's. */\n language?: string;\n /** Offer listing deleted content the reader holds. Default true. */\n includeDeleted?: boolean;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** The signed-in reader's content filters: show or hide each configured group, and go back to its default. */\nexport function ContentFilterSettings(p: ContentFilterSettingsProps) {\n const m = useMessages();\n const { t } = m;\n const id = useId();\n const ctx = useContext(ContentKitContext);\n const f = useContentFilters({ language: p.language, client: p.client });\n const save = useAction(\"filters.save\", p.onError);\n const root = (children: React.ReactNode) => (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-3 text-sm\", p.className)} data-ckui=\"content-filters\">\n {children}\n </ContentKitUiRoot>\n );\n if (ctx?.viewer === null) return root(<p className=\"text-muted-foreground\">{t(\"contents.filtersSignedOut\")}</p>);\n if (!f.filters) {\n if (f.error) return root(<ErrorLine>{contentError(m, f.error)}</ErrorLine>);\n return root(<Skeleton className=\"h-24 w-full\" />);\n }\n const filters = f.filters;\n if (!filters.filters.length && p.includeDeleted === false) return null;\n return root(\n <>\n {filters.filters.length ? (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\">\n {filters.filters.map((x) => (\n <li key={x.group.id} className=\"flex flex-wrap items-center gap-3 p-3\" data-ckui=\"content-filter\" data-slug={x.group.slug} data-visible={x.visible}>\n <Switch id={`${id}-${x.group.id}`} checked={x.visible} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setVisible(x.group.id, v))} />\n <Label htmlFor={`${id}-${x.group.id}`} className=\"min-w-0 flex-1\">\n {x.label || x.group.name}\n </Label>\n <span className=\"text-xs text-muted-foreground\">{t(x.visible ? \"contents.shown\" : \"contents.hidden\")}</span>\n {x.overridden && (\n <Button\n size=\"xs\"\n variant=\"ghost\"\n disabled={save.pending}\n onClick={() =>\n void save.run(() =>\n f.save({\n filters: filters.filters.filter((y) => y.overridden && y.group.id !== x.group.id).map((y) => ({ group_id: y.group.id, visible: y.visible })),\n include_deleted: filters.include_deleted,\n }),\n )\n }\n >\n {t(\"contents.useDefault\")}\n </Button>\n )}\n </li>\n ))}\n </ul>\n ) : null}\n {p.includeDeleted !== false && (\n <div className=\"flex items-center gap-3\">\n <Switch id={`${id}-deleted`} checked={filters.include_deleted} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setIncludeDeleted(v))} />\n <Label htmlFor={`${id}-deleted`}>{t(\"contents.includeDeleted\")}</Label>\n </div>\n )}\n <ErrorLine error={save.error} />\n </>,\n );\n}\n\nexport interface ReleaseDateIndexProps {\n /** Which contents count: the listing's filters. */\n query?: ReleaseDatesQuery;\n /** The bucket chosen (a day YYYY-MM-DD or month YYYY-MM): list with released_on set to it. */\n selected?: string;\n onSelect?: (date: string) => void;\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** The release date index: per month or day, newest first, how many contents and how many free. */\nexport function ReleaseDateIndex({ query = {}, selected, onSelect, client, className, appearance }: ReleaseDateIndexProps) {\n const m = useMessages();\n const { t } = m;\n const dates = useReleaseDates(query, { client });\n const label = (date: string) => {\n const [y, mo, d] = date.split(\"-\").map(Number);\n const at = new Date(Date.UTC(y!, (mo ?? 1) - 1, d ?? 1));\n return new Intl.DateTimeFormat(m.language, d ? { dateStyle: \"medium\", timeZone: \"UTC\" } : { year: \"numeric\", month: \"long\", timeZone: \"UTC\" }).format(at);\n };\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-2 text-sm\", className)} data-ckui=\"release-dates\">\n {dates.loading && !dates.items.length ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : dates.error && !dates.items.length ? (\n <ErrorLine>{contentError(m, dates.error)}</ErrorLine>\n ) : !dates.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"contents.noDates\")}</p>\n ) : (\n <ul className=\"grid gap-1\">\n {dates.items.map((d) => (\n <li key={d.date}>\n <button\n type=\"button\"\n aria-pressed={selected === d.date}\n className={cn(\"flex w-full items-center justify-between gap-3 rounded-md px-2 py-1.5 text-start hover:bg-muted\", selected === d.date && \"bg-muted font-medium\")}\n onClick={() => onSelect?.(d.date)}\n data-ckui=\"release-date\"\n data-date={d.date}\n >\n <span>{label(d.date)}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {m.plural(\"contents.items\", d.count)}\n {d.free < d.count && ` · ${m.plural(\"contents.free\", d.free)}`}\n </span>\n </button>\n </li>\n ))}\n </ul>\n )}\n {dates.hasMore && (\n <Button variant=\"outline\" size=\"sm\" className=\"justify-self-center\" disabled={dates.loadingMore} onClick={() => void dates.loadMore()}>\n {t(\"contents.loadMore\")}\n </Button>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filters.js","names":[],"sources":["../../../src/components/content/filters.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useContext, useId } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ReleaseDatesQuery } from \"../../client/discovery.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentFilters, useReleaseDates } from \"../../react/discovery.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { Switch } from \"#ckui/ui/switch\";\nimport { contentError, ErrorLine, useAction } from \"../social/parts.js\";\n\nexport interface ContentFilterSettingsProps {\n /** Labels and group names in this language; default the provider's. */\n language?: string;\n /** Offer listing deleted content the reader holds. Default true. */\n includeDeleted?: boolean;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** The signed-in reader's content filters: show or hide each configured group. */\nexport function ContentFilterSettings(p: ContentFilterSettingsProps) {\n const m = useMessages();\n const { t } = m;\n const id = useId();\n const ctx = useContext(ContentKitContext);\n const f = useContentFilters({ language: p.language, client: p.client });\n const save = useAction(\"filters.save\", p.onError);\n const root = (children: React.ReactNode) => (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-3 text-sm\", p.className)} data-ckui=\"content-filters\">\n {children}\n </ContentKitUiRoot>\n );\n if (ctx?.viewer === null) return root(<p className=\"text-muted-foreground\">{t(\"contents.filtersSignedOut\")}</p>);\n if (!f.filters) {\n if (f.error) return root(<ErrorLine>{contentError(m, f.error)}</ErrorLine>);\n return root(<Skeleton className=\"h-24 w-full\" />);\n }\n const filters = f.filters;\n if (!filters.filters.length && p.includeDeleted === false) return null;\n return root(\n <>\n {filters.filters.length ? (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\">\n {filters.filters.map((x) => (\n <li key={x.group.id} className=\"flex flex-wrap items-center gap-3 p-3\" data-ckui=\"content-filter\" data-slug={x.group.slug} data-visible={x.visible}>\n <Switch id={`${id}-${x.group.id}`} checked={x.visible} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setVisible(x.group.id, v))} />\n <Label htmlFor={`${id}-${x.group.id}`} className=\"min-w-0 flex-1\">\n {x.label || x.group.name}\n </Label>\n </li>\n ))}\n </ul>\n ) : null}\n {p.includeDeleted !== false && (\n <div className=\"flex items-center gap-3\">\n <Switch id={`${id}-deleted`} checked={filters.include_deleted} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setIncludeDeleted(v))} />\n <Label htmlFor={`${id}-deleted`}>{t(\"contents.includeDeleted\")}</Label>\n </div>\n )}\n <ErrorLine error={save.error} />\n </>,\n );\n}\n\nexport interface ReleaseDateIndexProps {\n /** Which contents count: the listing's filters. */\n query?: ReleaseDatesQuery;\n /** The bucket chosen (a day YYYY-MM-DD or month YYYY-MM): list with released_on set to it. */\n selected?: string;\n onSelect?: (date: string) => void;\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** The release date index: per month or day, newest first, how many contents and how many free. */\nexport function ReleaseDateIndex({ query = {}, selected, onSelect, client, className, appearance }: ReleaseDateIndexProps) {\n const m = useMessages();\n const { t } = m;\n const dates = useReleaseDates(query, { client });\n const label = (date: string) => {\n const [y, mo, d] = date.split(\"-\").map(Number);\n const at = new Date(Date.UTC(y!, (mo ?? 1) - 1, d ?? 1));\n return new Intl.DateTimeFormat(m.language, d ? { dateStyle: \"medium\", timeZone: \"UTC\" } : { year: \"numeric\", month: \"long\", timeZone: \"UTC\" }).format(at);\n };\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-2 text-sm\", className)} data-ckui=\"release-dates\">\n {dates.loading && !dates.items.length ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : dates.error && !dates.items.length ? (\n <ErrorLine>{contentError(m, dates.error)}</ErrorLine>\n ) : !dates.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"contents.noDates\")}</p>\n ) : (\n <ul className=\"grid gap-1\">\n {dates.items.map((d) => (\n <li key={d.date}>\n <button\n type=\"button\"\n aria-pressed={selected === d.date}\n className={cn(\"flex w-full items-center justify-between gap-3 rounded-md px-2 py-1.5 text-start hover:bg-muted\", selected === d.date && \"bg-muted font-medium\")}\n onClick={() => onSelect?.(d.date)}\n data-ckui=\"release-date\"\n data-date={d.date}\n >\n <span>{label(d.date)}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {m.plural(\"contents.items\", d.count)}\n {d.free < d.count && ` · ${m.plural(\"contents.free\", d.free)}`}\n </span>\n </button>\n </li>\n ))}\n </ul>\n )}\n {dates.hasMore && (\n <Button variant=\"outline\" size=\"sm\" className=\"justify-self-center\" disabled={dates.loadingMore} onClick={() => void dates.loadMore()}>\n {t(\"contents.loadMore\")}\n </Button>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export { ContentCard, OwnerChip, PostCard, lockLabel, type ContentCardProps, type PostCardProps } from './card.js';
2
2
  export { CardGrid, ContentGrid, ContentHistory, ContentRail, SearchResults, type CardListProps, type ContentRailProps, type LockedCards } from './grid.js';
3
3
  export { SearchBox, type SearchBoxProps } from './search.js';
4
+ export { ReaderSettings, type ReaderSettingsProps } from './reader-settings.js';
4
5
  export { ContentFilterSettings, ReleaseDateIndex, type ContentFilterSettingsProps, type ReleaseDateIndexProps } from './filters.js';
5
6
  export { ContentListing, sortLabel, type ContentListingProps } from './listing.js';
6
7
  export { Paywall, VersionPicker, priceLabel, useVersionMenuItems, type PaywallProps, type VersionMenuOptions, type VersionPickerProps } from './paywall.js';
@@ -0,0 +1,19 @@
1
+ import { ContentKitUiAppearance } from '../../appearance.js';
2
+ import { ContentKitClient } from '../../client/client.js';
3
+ import { ContentKitErrorHandler } from '../../react/context.js';
4
+ export interface ReaderSettingsProps {
5
+ languages: readonly {
6
+ value: string;
7
+ label: string;
8
+ }[];
9
+ /** The current language, controlled by the host. */
10
+ language: string;
11
+ /** The host applies its own route and preference changes. */
12
+ onLanguageChange: (language: string) => void;
13
+ client?: ContentKitClient;
14
+ onError?: ContentKitErrorHandler;
15
+ className?: string;
16
+ appearance?: ContentKitUiAppearance;
17
+ }
18
+ /** One reader-settings dialog for language and the signed-in reader's filters. */
19
+ export declare function ReaderSettings(p: ReaderSettingsProps): import('react').JSX.Element;
@@ -0,0 +1,95 @@
1
+ import { useMessages as e } from "../../i18n/context.js";
2
+ import { AppearanceContext as t, ContentKitUiRoot as n } from "../../scope.js";
3
+ import { ContentKitContext as r } from "../../react/context.js";
4
+ import { Button as i } from "../../ui/button.js";
5
+ import { Dialog as a, DialogContent as o, DialogDescription as s, DialogHeader as c, DialogTitle as l, DialogTrigger as u } from "../../ui/dialog.js";
6
+ import { Label as d } from "../../ui/label.js";
7
+ import { Select as f, SelectContent as p, SelectItem as m, SelectTrigger as h, SelectValue as g } from "../../ui/select.js";
8
+ import { useContentFilters as _ } from "../../react/discovery.js";
9
+ import { ContentFilterSettings as v } from "./filters.js";
10
+ import { useContext as y, useId as b } from "react";
11
+ import { jsx as x, jsxs as S } from "react/jsx-runtime";
12
+ import { Settings01Icon as C } from "@hugeicons/core-free-icons";
13
+ import { HugeiconsIcon as w } from "@hugeicons/react";
14
+ //#region src/components/content/reader-settings.tsx
15
+ function T(_) {
16
+ let { t: v } = e(), T = b(), D = y(r)?.viewer, O = y(t), k = _.appearance ?? O;
17
+ return /* @__PURE__ */ x(t.Provider, {
18
+ value: k,
19
+ children: /* @__PURE__ */ x(n, {
20
+ className: _.className,
21
+ appearance: k,
22
+ "data-ckui": "reader-settings",
23
+ children: /* @__PURE__ */ S(a, { children: [/* @__PURE__ */ S(u, {
24
+ render: /* @__PURE__ */ x(i, {
25
+ type: "button",
26
+ variant: "ghost",
27
+ size: "sm",
28
+ "aria-label": v("readerSettings.title"),
29
+ "data-ckui": "reader-settings-trigger"
30
+ }),
31
+ children: [/* @__PURE__ */ x(w, {
32
+ icon: C,
33
+ strokeWidth: 2,
34
+ className: "size-4",
35
+ "aria-hidden": !0
36
+ }), /* @__PURE__ */ x("span", { children: _.language.toUpperCase() })]
37
+ }), /* @__PURE__ */ S(o, {
38
+ className: "max-h-[calc(100dvh-2rem)] overflow-y-auto",
39
+ children: [
40
+ /* @__PURE__ */ S(c, { children: [/* @__PURE__ */ x(l, { children: v("readerSettings.title") }), /* @__PURE__ */ x(s, {
41
+ className: "sr-only",
42
+ children: v("readerSettings.description")
43
+ })] }),
44
+ /* @__PURE__ */ S("div", {
45
+ className: "grid gap-3",
46
+ children: [/* @__PURE__ */ x(d, {
47
+ htmlFor: `${T}-language`,
48
+ children: v("listing.language")
49
+ }), /* @__PURE__ */ S(f, {
50
+ value: _.language,
51
+ onValueChange: (e) => {
52
+ e && e !== _.language && _.onLanguageChange(e);
53
+ },
54
+ children: [/* @__PURE__ */ x(h, {
55
+ id: `${T}-language`,
56
+ className: "w-full",
57
+ children: /* @__PURE__ */ x(g, { children: _.languages.find((e) => e.value === _.language)?.label ?? _.language })
58
+ }), /* @__PURE__ */ x(p, { children: _.languages.map((e) => /* @__PURE__ */ x(m, {
59
+ value: e.value,
60
+ children: e.label
61
+ }, e.value)) })]
62
+ })]
63
+ }),
64
+ D != null && /* @__PURE__ */ x(E, {
65
+ language: _.language,
66
+ client: _.client,
67
+ onError: _.onError
68
+ })
69
+ ]
70
+ })] })
71
+ })
72
+ });
73
+ }
74
+ function E(t) {
75
+ let { t: n } = e(), r = b(), { filters: i } = _({
76
+ language: t.language,
77
+ client: t.client
78
+ });
79
+ return i?.filters.length === 0 ? null : /* @__PURE__ */ S("section", {
80
+ "aria-labelledby": r,
81
+ className: "grid gap-3",
82
+ children: [/* @__PURE__ */ x("h3", {
83
+ id: r,
84
+ className: "font-medium",
85
+ children: n("readerSettings.filters")
86
+ }), /* @__PURE__ */ x(v, {
87
+ ...t,
88
+ includeDeleted: !1
89
+ })]
90
+ });
91
+ }
92
+ //#endregion
93
+ export { T as ReaderSettings };
94
+
95
+ //# sourceMappingURL=reader-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader-settings.js","names":[],"sources":["../../../src/components/content/reader-settings.tsx"],"sourcesContent":["import { Settings01Icon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { useContext, useId } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentFilters } from \"../../react/discovery.js\";\nimport { AppearanceContext, ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from \"#ckui/ui/dialog\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"#ckui/ui/select\";\nimport { ContentFilterSettings } from \"./filters.js\";\n\nexport interface ReaderSettingsProps {\n languages: readonly { value: string; label: string }[];\n /** The current language, controlled by the host. */\n language: string;\n /** The host applies its own route and preference changes. */\n onLanguageChange: (language: string) => void;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** One reader-settings dialog for language and the signed-in reader's filters. */\nexport function ReaderSettings(p: ReaderSettingsProps) {\n const { t } = useMessages();\n const id = useId();\n const viewer = useContext(ContentKitContext)?.viewer;\n const inheritedAppearance = useContext(AppearanceContext);\n const appearance = p.appearance ?? inheritedAppearance;\n return (\n <AppearanceContext.Provider value={appearance}>\n <ContentKitUiRoot className={p.className} appearance={appearance} data-ckui=\"reader-settings\">\n <Dialog>\n <DialogTrigger render={<Button type=\"button\" variant=\"ghost\" size=\"sm\" aria-label={t(\"readerSettings.title\")} data-ckui=\"reader-settings-trigger\" />}>\n <HugeiconsIcon icon={Settings01Icon} strokeWidth={2} className=\"size-4\" aria-hidden />\n <span>{p.language.toUpperCase()}</span>\n </DialogTrigger>\n <DialogContent className=\"max-h-[calc(100dvh-2rem)] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>{t(\"readerSettings.title\")}</DialogTitle>\n <DialogDescription className=\"sr-only\">{t(\"readerSettings.description\")}</DialogDescription>\n </DialogHeader>\n <div className=\"grid gap-3\">\n <Label htmlFor={`${id}-language`}>{t(\"listing.language\")}</Label>\n <Select value={p.language} onValueChange={(value) => { if (value && value !== p.language) p.onLanguageChange(value); }}>\n <SelectTrigger id={`${id}-language`} className=\"w-full\">\n <SelectValue>{p.languages.find((item) => item.value === p.language)?.label ?? p.language}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {p.languages.map((item) => <SelectItem key={item.value} value={item.value}>{item.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </div>\n {viewer != null && <ReaderFilters language={p.language} client={p.client} onError={p.onError} />}\n </DialogContent>\n </Dialog>\n </ContentKitUiRoot>\n </AppearanceContext.Provider>\n );\n}\n\nfunction ReaderFilters(p: Pick<ReaderSettingsProps, \"language\" | \"client\" | \"onError\">) {\n const { t } = useMessages();\n const id = useId();\n const { filters } = useContentFilters({ language: p.language, client: p.client });\n if (filters?.filters.length === 0) return null;\n return (\n <section aria-labelledby={id} className=\"grid gap-3\">\n <h3 id={id} className=\"font-medium\">{t(\"readerSettings.filters\")}</h3>\n <ContentFilterSettings {...p} includeDeleted={false} />\n </section>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AA4BA,SAAgB,EAAe,GAAwB;CACrD,IAAM,EAAE,SAAM,EAAY,GACpB,IAAK,EAAM,GACX,IAAS,EAAW,CAAiB,CAAC,EAAE,QACxC,IAAsB,EAAW,CAAiB,GAClD,IAAa,EAAE,cAAc;CACnC,OACE,kBAAC,EAAkB,UAAnB;EAA4B,OAAO;EACjC,UAAA,kBAAC,GAAD;GAAkB,WAAW,EAAE;GAAuB;GAAY,aAAU;GAC1E,UAAA,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;IAAe,QAAQ,kBAAC,GAAD;KAAQ,MAAK;KAAS,SAAQ;KAAQ,MAAK;KAAK,cAAY,EAAE,sBAAsB;KAAG,aAAU;IAA2B,CAAA;IAAnJ,UAAA,CACE,kBAAC,GAAD;KAAe,MAAM;KAAgB,aAAa;KAAG,WAAU;KAAS,eAAA;IAAa,CAAA,GACrF,kBAAC,QAAD,EAAA,UAAO,EAAE,SAAS,YAAY,EAAQ,CAAA,CACzB;GACf,CAAA,GAAA,kBAAC,GAAD;IAAe,WAAU;IAAzB,UAAA;KACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAc,EAAE,sBAAsB,EAAe,CAAA,GACrD,kBAAC,GAAD;MAAmB,WAAU;MAAW,UAAA,EAAE,4BAA4B;KAAqB,CAAA,CAC/E,EAAA,CAAA;KACd,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,GAAD;OAAO,SAAS,GAAG,EAAG;OAAa,UAAA,EAAE,kBAAkB;MAAS,CAAA,GAChE,kBAAC,GAAD;OAAQ,OAAO,EAAE;OAAU,gBAAgB,MAAU;QAAE,AAAI,KAAS,MAAU,EAAE,YAAU,EAAE,iBAAiB,CAAK;OAAG;OAArH,UAAA,CACE,kBAAC,GAAD;QAAe,IAAI,GAAG,EAAG;QAAY,WAAU;QAC7C,UAAA,kBAAC,GAAD,EAAA,UAAc,EAAE,UAAU,MAAM,MAAS,EAAK,UAAU,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAsB,CAAA;OACzF,CAAA,GACf,kBAAC,GAAD,EAAA,UACG,EAAE,UAAU,KAAK,MAAS,kBAAC,GAAD;QAA6B,OAAO,EAAK;QAAQ,UAAA,EAAK;OAAkB,GAAvD,EAAK,KAAkD,CAAC,EACvF,CAAA,CACT;MACL,CAAA,CAAA;;KACJ,KAAU,QAAQ,kBAAC,GAAD;MAAe,UAAU,EAAE;MAAU,QAAQ,EAAE;MAAQ,SAAS,EAAE;KAAU,CAAA;IAClF;GACT,CAAA,CAAA,EAAA,CAAA;EACQ,CAAA;CACQ,CAAA;AAEhC;AAEA,SAAS,EAAc,GAAiE;CACtF,IAAM,EAAE,SAAM,EAAY,GACpB,IAAK,EAAM,GACX,EAAE,eAAY,EAAkB;EAAE,UAAU,EAAE;EAAU,QAAQ,EAAE;CAAO,CAAC;CAEhF,OADI,GAAS,QAAQ,WAAW,IAAU,OAExC,kBAAC,WAAD;EAAS,mBAAiB;EAAI,WAAU;EAAxC,UAAA,CACE,kBAAC,MAAD;GAAQ;GAAI,WAAU;GAAe,UAAA,EAAE,wBAAwB;EAAM,CAAA,GACrE,kBAAC,GAAD;GAAuB,GAAI;GAAG,gBAAgB;EAAQ,CAAA,CAC/C;;AAEb"}
@@ -16,6 +16,8 @@ export interface SearchBoxProps {
16
16
  labels?: Labels;
17
17
  /** The reader's recent searches while the box is empty. Default true. */
18
18
  recent?: boolean;
19
+ /** Header-wide dropdown under the nearest header/banner; default stays inline. */
20
+ presentation?: "inline" | "header";
19
21
  client?: ContentKitClient;
20
22
  className?: string;
21
23
  appearance?: ContentKitUiAppearance;