@yimingliao/cms 0.0.146 → 0.0.147

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 (89) hide show
  1. package/dist/export/client/components/index.js +69 -0
  2. package/dist/src/client/applications/ui/use-parent-pathname.js +10 -0
  3. package/dist/src/client/interfaces/components/admin-initializer.js +29 -0
  4. package/dist/src/client/interfaces/components/resources/file/file-card.js +87 -0
  5. package/dist/src/client/interfaces/components/resources/file/file-list.js +159 -0
  6. package/dist/src/client/interfaces/components/resources/file/is-locked-buttons.js +71 -0
  7. package/dist/src/client/interfaces/components/resources/file/type-buttons.js +62 -0
  8. package/dist/src/client/interfaces/components/shadcn/sidebar.js +1 -1
  9. package/dist/src/client/interfaces/components/ui/blocks/list-cards-container/list-cards-container.js +96 -0
  10. package/dist/src/client/interfaces/components/ui/blocks/list-cards-container/page-size-selector.js +63 -0
  11. package/dist/src/client/interfaces/components/ui/blocks/list-cards-container/pagination.js +94 -0
  12. package/dist/src/client/interfaces/components/ui/blocks/page-header/page-header-title.js +26 -0
  13. package/dist/src/client/interfaces/components/ui/blocks/page-header/page-header.js +74 -0
  14. package/dist/src/client/interfaces/components/ui/blocks/page-header/presets/batch-create.js +33 -0
  15. package/dist/src/client/interfaces/components/ui/blocks/page-header/presets/batch.js +39 -0
  16. package/dist/src/client/interfaces/components/ui/blocks/page-header/presets/create.js +33 -0
  17. package/dist/src/client/interfaces/components/ui/blocks/page-header/presets/edit.js +33 -0
  18. package/dist/src/client/interfaces/components/ui/blocks/page-header/presets/index.js +48 -0
  19. package/dist/src/client/interfaces/components/ui/blocks/page-header/presets/show.js +61 -0
  20. package/dist/src/client/interfaces/components/ui/blocks/page-header/presets/trash.js +39 -0
  21. package/dist/src/client/interfaces/components/ui/buttons/return-button.js +61 -0
  22. package/dist/src/client/interfaces/components/ui/cards/action-buttons-card.js +82 -0
  23. package/dist/src/client/interfaces/components/ui/cards/resource-card/card-status-bar.js +51 -0
  24. package/dist/src/client/interfaces/components/ui/cards/resource-card/card-text-content.js +38 -0
  25. package/dist/src/client/interfaces/components/ui/cards/resource-card/resource-card.js +77 -0
  26. package/dist/src/client/interfaces/components/ui/display/array-list.js +69 -0
  27. package/dist/src/client/interfaces/components/ui/display/badge.js +41 -0
  28. package/dist/src/client/interfaces/components/ui/display/html-display.js +32 -0
  29. package/dist/src/client/interfaces/components/ui/display/object-array-list.js +75 -0
  30. package/dist/src/client/interfaces/components/ui/features/accordion/accordion-container.js +31 -0
  31. package/dist/src/client/interfaces/components/ui/features/accordion/accordion-header.js +34 -0
  32. package/dist/src/client/interfaces/components/ui/features/accordion/accordion.js +81 -0
  33. package/dist/src/client/interfaces/components/ui/features/expandable-list/expand-bar.js +39 -0
  34. package/dist/src/client/interfaces/components/ui/features/expandable-list/expandable-list-content.js +49 -0
  35. package/dist/src/client/interfaces/components/ui/features/expandable-list/expandable-list.js +53 -0
  36. package/dist/src/client/interfaces/components/ui/features/external-link.js +15 -0
  37. package/dist/src/client/interfaces/components/ui/features/file/file-info/file-info.js +118 -0
  38. package/dist/src/client/interfaces/components/ui/features/file/file-info/file-name.js +48 -0
  39. package/dist/src/client/interfaces/components/ui/features/file/file-picker/file-picker-container.js +74 -0
  40. package/dist/src/client/interfaces/components/ui/features/file/file-picker/file-picker-placeholder.js +48 -0
  41. package/dist/src/client/interfaces/components/ui/features/file/file-picker/file-picker.js +109 -0
  42. package/dist/src/client/interfaces/components/ui/features/file/file-preview/file-preview-list.js +85 -0
  43. package/dist/src/client/interfaces/components/ui/features/file/file-preview/file-preview-meta.js +40 -0
  44. package/dist/src/client/interfaces/components/ui/features/file/file-preview/file-preview.js +113 -0
  45. package/dist/src/client/interfaces/components/ui/features/file/uploader.js +101 -0
  46. package/dist/src/client/interfaces/components/ui/features/pick-modal/pick-modal-body.js +112 -0
  47. package/dist/src/client/interfaces/components/ui/features/pick-modal/pick-modal-trigger.js +97 -0
  48. package/dist/src/client/interfaces/components/ui/features/pick-modal/pick-modal.js +77 -0
  49. package/dist/src/client/interfaces/components/ui/features/smart-image.js +57 -0
  50. package/dist/src/client/interfaces/components/ui/features/tick.js +27 -0
  51. package/dist/src/client/interfaces/components/ui/form/containers/fields-container.js +24 -0
  52. package/dist/src/client/interfaces/components/ui/form/containers/main-fields.js +25 -0
  53. package/dist/src/client/interfaces/components/ui/form/containers/side-fields.js +24 -0
  54. package/dist/src/client/interfaces/components/ui/form/control-fields/built-in-fields.js +9 -0
  55. package/dist/src/client/interfaces/components/ui/form/control-fields/control-fields-display.js +112 -0
  56. package/dist/src/client/interfaces/components/ui/form/control-fields/control-fields-input.js +158 -0
  57. package/dist/src/client/interfaces/components/ui/form/control-fields/control-fields.js +59 -0
  58. package/dist/src/client/interfaces/components/ui/form/field-body.js +79 -0
  59. package/dist/src/client/interfaces/components/ui/form/index-field.js +87 -0
  60. package/dist/src/client/interfaces/components/ui/form/slug-field.js +82 -0
  61. package/dist/src/client/interfaces/components/ui/inputs/array-input.js +110 -0
  62. package/dist/src/client/interfaces/components/ui/inputs/checkbox.js +93 -0
  63. package/dist/src/client/interfaces/components/ui/inputs/editor/base/base-editor.js +143 -0
  64. package/dist/src/client/interfaces/components/ui/inputs/editor/base/built-in-plugins.js +71 -0
  65. package/dist/src/client/interfaces/components/ui/inputs/editor/base/configs/heading.config.js +41 -0
  66. package/dist/src/client/interfaces/components/ui/inputs/editor/base/configs/image.config.js +32 -0
  67. package/dist/src/client/interfaces/components/ui/inputs/editor/base/configs/table.config.js +15 -0
  68. package/dist/src/client/interfaces/components/ui/inputs/editor/editor.js +112 -0
  69. package/dist/src/client/interfaces/components/ui/inputs/editor/plugins/asset-manager/asset-manager.js +24 -0
  70. package/dist/src/client/interfaces/components/ui/inputs/editor/plugins/asset-manager/use-control-asset-mamager.js +26 -0
  71. package/dist/src/client/interfaces/components/ui/inputs/editor/plugins/file-repository/upload-adapter.js +84 -0
  72. package/dist/src/client/interfaces/components/ui/inputs/editor/plugins/word-count-display/icons.js +17 -0
  73. package/dist/src/client/interfaces/components/ui/inputs/editor/plugins/word-count-display/word-count-display.js +81 -0
  74. package/dist/src/client/interfaces/components/ui/inputs/editor/use-init-editor/use-init-editor.js +50 -0
  75. package/dist/src/client/interfaces/components/ui/inputs/search-input.js +61 -0
  76. package/dist/src/client/interfaces/components/ui/inputs/select.js +69 -0
  77. package/dist/src/client/interfaces/components/ui/inputs/textarea.js +62 -0
  78. package/dist/src/client/interfaces/components/ui/layouts/content-container.js +38 -0
  79. package/dist/src/client/interfaces/components/ui/layouts/navbar/i18n-selector.js +42 -0
  80. package/dist/src/client/interfaces/components/ui/layouts/navbar/nav-user.js +106 -0
  81. package/dist/src/client/interfaces/components/ui/layouts/navbar/navbar.js +84 -0
  82. package/dist/src/client/interfaces/components/ui/layouts/navbar/sign-out-button.js +58 -0
  83. package/dist/src/client/interfaces/components/ui/layouts/navbar/theme-selector.js +51 -0
  84. package/dist/src/client/interfaces/components/ui/layouts/sidebar/nav-main.js +99 -0
  85. package/dist/src/client/interfaces/styles/constants.js +3 -1
  86. package/dist/src/constants/file.js +27 -0
  87. package/dist/src/shared/list-items.js +3 -0
  88. package/dist/src/shared/utils/debounce.js +14 -0
  89. package/package.json +1 -1
@@ -0,0 +1,81 @@
1
+ import { Plugin, ButtonView } from 'ckeditor5';
2
+ import 'mime-types';
3
+ import { debounce } from '../../../../../../../../shared/utils/debounce.js';
4
+ import { HTML_ICON, CHARACTERS_ICON, WORDS_ICON } from './icons.js';
5
+
6
+ const WORD_COUNT = "WordCount";
7
+ const WORD_COUNT_DISPLAY_PLUGIN_NAME = {
8
+ default: "word-count-display",
9
+ // CSS Class
10
+ characters: "word-count-display-characters",
11
+ // Plugin Name, CSS Class
12
+ words: "word-count-display-words",
13
+ // Plugin Name, CSS Class
14
+ html: "word-count-display-html"
15
+ // Plugin Name, CSS Class
16
+ };
17
+ class WordCountButtons extends Plugin {
18
+ init() {
19
+ const editor = this.editor;
20
+ const wordCountPlugin = editor.plugins.get(WORD_COUNT);
21
+ editor.ui.componentFactory.add(
22
+ WORD_COUNT_DISPLAY_PLUGIN_NAME.html,
23
+ (locale) => {
24
+ const button = new ButtonView(locale);
25
+ button.set({
26
+ icon: HTML_ICON,
27
+ label: `${editor.getData()?.length}`,
28
+ tooltip: true,
29
+ withText: true,
30
+ isEnabled: false,
31
+ class: `${WORD_COUNT_DISPLAY_PLUGIN_NAME.default} ${WORD_COUNT_DISPLAY_PLUGIN_NAME.html}`
32
+ });
33
+ const update = debounce(
34
+ () => button.label = `${editor.getData()?.length}`
35
+ );
36
+ editor.model.document.on("change:data", update);
37
+ return button;
38
+ }
39
+ );
40
+ editor.ui.componentFactory.add(
41
+ WORD_COUNT_DISPLAY_PLUGIN_NAME.characters,
42
+ (locale) => {
43
+ const button = new ButtonView(locale);
44
+ button.set({
45
+ icon: CHARACTERS_ICON,
46
+ label: `${wordCountPlugin.characters}`,
47
+ tooltip: true,
48
+ withText: true,
49
+ isEnabled: false,
50
+ class: `${WORD_COUNT_DISPLAY_PLUGIN_NAME.default} ${WORD_COUNT_DISPLAY_PLUGIN_NAME.characters}`
51
+ });
52
+ const update = debounce(
53
+ () => button.label = `${wordCountPlugin.characters}`
54
+ );
55
+ wordCountPlugin.on("change:characters", update);
56
+ return button;
57
+ }
58
+ );
59
+ editor.ui.componentFactory.add(
60
+ WORD_COUNT_DISPLAY_PLUGIN_NAME.words,
61
+ (locale) => {
62
+ const button = new ButtonView(locale);
63
+ button.set({
64
+ icon: WORDS_ICON,
65
+ label: `${wordCountPlugin.words}`,
66
+ tooltip: true,
67
+ withText: true,
68
+ isEnabled: false,
69
+ class: `${WORD_COUNT_DISPLAY_PLUGIN_NAME.default} ${WORD_COUNT_DISPLAY_PLUGIN_NAME.words}`
70
+ });
71
+ const update = debounce(
72
+ () => button.label = `${wordCountPlugin.words}`
73
+ );
74
+ wordCountPlugin.on("change:words", update);
75
+ return button;
76
+ }
77
+ );
78
+ }
79
+ }
80
+
81
+ export { WORD_COUNT_DISPLAY_PLUGIN_NAME, WordCountButtons as default };
@@ -0,0 +1,50 @@
1
+ import { FileRepository } from 'ckeditor5';
2
+ import { useRef, useEffect } from 'react';
3
+ import 'mime-types';
4
+ import { debounce } from '../../../../../../../shared/utils/debounce.js';
5
+ import { BaseEditor } from '../base/base-editor.js';
6
+ import { OPEN_ASSET_MANAGER_KEY } from '../plugins/asset-manager/asset-manager.js';
7
+ import 'intor/react';
8
+
9
+ const DOCUMENT_EVENTS = {
10
+ CHANGE: "change"};
11
+ const useInitEditor = ({
12
+ enabled = true,
13
+ containerRef,
14
+ locale,
15
+ value,
16
+ onEditorChange,
17
+ createUploadAdapter,
18
+ openAssetManager
19
+ }) => {
20
+ const editorRef = useRef(null);
21
+ useEffect(() => {
22
+ if (!enabled || !containerRef.current) return;
23
+ BaseEditor.create(containerRef.current, {
24
+ ...BaseEditor.defaultConfig,
25
+ language: locale,
26
+ initialData: value
27
+ }).then((editor) => {
28
+ editorRef.current = editor;
29
+ const debouncedChange = debounce(
30
+ () => onEditorChange?.(editor.getData())
31
+ );
32
+ editor.model.document.on(DOCUMENT_EVENTS.CHANGE, debouncedChange);
33
+ editor.plugins.get(FileRepository.pluginName).createUploadAdapter = createUploadAdapter;
34
+ editor.config.set(OPEN_ASSET_MANAGER_KEY, openAssetManager);
35
+ return () => {
36
+ editor.model.document.off(DOCUMENT_EVENTS.CHANGE, debouncedChange);
37
+ debouncedChange.clear();
38
+ };
39
+ }).catch((error) => {
40
+ console.error("CKEditor init error:", error);
41
+ });
42
+ return () => {
43
+ void editorRef.current?.destroy();
44
+ editorRef.current = null;
45
+ };
46
+ }, [enabled, containerRef]);
47
+ return editorRef;
48
+ };
49
+
50
+ export { useInitEditor };
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { useTranslator } from 'intor/react';
4
+ import { Search } from 'lucide-react';
5
+ import { useRef, useState } from 'react';
6
+ import '@radix-ui/react-avatar';
7
+ import 'ua-parser-js';
8
+ import 'clsx';
9
+ import 'tailwind-merge';
10
+ import 'next/navigation';
11
+ import '../../shadcn/badge.js';
12
+ import '../../shadcn/button.js';
13
+ import '@radix-ui/react-collapsible';
14
+ import '@radix-ui/react-dialog';
15
+ import '@radix-ui/react-dropdown-menu';
16
+ import { InputGroupAddon } from '../../shadcn/input-group.js';
17
+ import '@radix-ui/react-label';
18
+ import '@radix-ui/react-select';
19
+ import '@radix-ui/react-separator';
20
+ import '../../shadcn/sidebar.js';
21
+ import { Spinner } from '../../shadcn/spinner.js';
22
+ import '@radix-ui/react-tooltip';
23
+ import { Input } from './input.js';
24
+
25
+ function SearchInput({
26
+ searchString = "",
27
+ setSearchString,
28
+ isLoading = false,
29
+ isDisabled = false,
30
+ ...props
31
+ }) {
32
+ const { t } = useTranslator();
33
+ const isComposingRef = useRef(false);
34
+ const [inputValue, setInputValue] = useState(searchString);
35
+ const handleCompositionEnd = (e) => {
36
+ isComposingRef.current = false;
37
+ setInputValue(e.currentTarget.value);
38
+ setSearchString(e.currentTarget.value);
39
+ };
40
+ const handleChange = (e) => {
41
+ setInputValue(e.target.value);
42
+ if (!isComposingRef.current) setSearchString(e.target.value);
43
+ };
44
+ return /* @__PURE__ */ jsx("div", { className: "relative size-full", children: /* @__PURE__ */ jsx(
45
+ Input,
46
+ {
47
+ isDisabled,
48
+ placeholder: isLoading ? "" : t("ui.search.text"),
49
+ autoComplete: "off",
50
+ value: inputValue,
51
+ onChange: handleChange,
52
+ onCompositionStart: () => isComposingRef.current = true,
53
+ onCompositionEnd: handleCompositionEnd,
54
+ className: "w-full pr-9",
55
+ ...props,
56
+ children: /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: isLoading ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(Search, {}) })
57
+ }
58
+ ) });
59
+ }
60
+
61
+ export { SearchInput };
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import 'react';
4
+ import 'ua-parser-js';
5
+ import { cn } from '../../../../applications/shadcn/utils.js';
6
+ import 'next/navigation';
7
+ import '@radix-ui/react-avatar';
8
+ import '../../shadcn/badge.js';
9
+ import '../../shadcn/button.js';
10
+ import '@radix-ui/react-collapsible';
11
+ import '@radix-ui/react-dialog';
12
+ import 'lucide-react';
13
+ import '@radix-ui/react-dropdown-menu';
14
+ import '../../shadcn/input-group.js';
15
+ import '@radix-ui/react-label';
16
+ import { SelectItem, Select as Select$1, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectLabel } from '../../shadcn/select.js';
17
+ import '@radix-ui/react-separator';
18
+ import '../../shadcn/sidebar.js';
19
+ import '@radix-ui/react-tooltip';
20
+
21
+ function Select({
22
+ // form context
23
+ fieldName,
24
+ setFormData,
25
+ // ui states
26
+ isDisabled = false,
27
+ isLoading = false,
28
+ // base
29
+ placeholder,
30
+ label,
31
+ className,
32
+ children,
33
+ ...props
34
+ }) {
35
+ return /* @__PURE__ */ jsxs(
36
+ Select$1,
37
+ {
38
+ onValueChange: (value) => {
39
+ if (!setFormData || !fieldName) return;
40
+ setFormData((p) => ({ ...p, [fieldName]: value }));
41
+ },
42
+ disabled: isDisabled || isLoading,
43
+ ...props,
44
+ children: [
45
+ /* @__PURE__ */ jsx(
46
+ SelectTrigger,
47
+ {
48
+ className: cn("w-full", className),
49
+ disabled: isDisabled || isLoading,
50
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
51
+ }
52
+ ),
53
+ /* @__PURE__ */ jsx(SelectContent, { children: /* @__PURE__ */ jsxs(SelectGroup, { children: [
54
+ label && /* @__PURE__ */ jsx(SelectLabel, { children: label }),
55
+ children
56
+ ] }) })
57
+ ]
58
+ }
59
+ );
60
+ }
61
+ function Option({
62
+ value,
63
+ isDisabled = false,
64
+ children
65
+ }) {
66
+ return /* @__PURE__ */ jsx(SelectItem, { value, disabled: isDisabled, children });
67
+ }
68
+
69
+ export { Option, Select };
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { jsx, Fragment } from 'react/jsx-runtime';
3
+ import { useRef, useEffect } from 'react';
4
+ import '@radix-ui/react-avatar';
5
+ import 'ua-parser-js';
6
+ import 'clsx';
7
+ import 'tailwind-merge';
8
+ import 'next/navigation';
9
+ import '../../shadcn/badge.js';
10
+ import '../../shadcn/button.js';
11
+ import '@radix-ui/react-collapsible';
12
+ import '@radix-ui/react-dialog';
13
+ import 'lucide-react';
14
+ import '@radix-ui/react-dropdown-menu';
15
+ import { InputGroup, InputGroupAddon } from '../../shadcn/input-group.js';
16
+ import '@radix-ui/react-label';
17
+ import '@radix-ui/react-select';
18
+ import '@radix-ui/react-separator';
19
+ import '../../shadcn/sidebar.js';
20
+ import { Spinner } from '../../shadcn/spinner.js';
21
+ import { Textarea as Textarea$1 } from '../../shadcn/textarea.js';
22
+ import '@radix-ui/react-tooltip';
23
+
24
+ function Textarea({
25
+ // form context
26
+ fieldName,
27
+ setFormData,
28
+ // ui states
29
+ isLoading = false,
30
+ isDisabled = false,
31
+ isError = false,
32
+ // base
33
+ ...props
34
+ }) {
35
+ isDisabled = isDisabled || isLoading;
36
+ const textareaRef = useRef(null);
37
+ const resetHeight = (element) => {
38
+ element.style.height = "40px";
39
+ element.style.height = `${element.scrollHeight + 2}px`;
40
+ };
41
+ useEffect(() => {
42
+ if (!textareaRef.current) return;
43
+ resetHeight(textareaRef.current);
44
+ }, [props.value, isLoading]);
45
+ return /* @__PURE__ */ jsx(Fragment, { children: isLoading ? /* @__PURE__ */ jsx(InputGroup, { "data-disabled": isDisabled, className: "h-10", children: /* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(Spinner, {}) }) }) : /* @__PURE__ */ jsx(
46
+ Textarea$1,
47
+ {
48
+ ref: textareaRef,
49
+ disabled: isDisabled,
50
+ "aria-invalid": isError,
51
+ value: isLoading ? "" : props.value,
52
+ onChange: (e) => {
53
+ resetHeight(e.target);
54
+ if (!setFormData || !fieldName) return;
55
+ setFormData((p) => ({ ...p, [fieldName]: e.target.value }));
56
+ },
57
+ ...props
58
+ }
59
+ ) });
60
+ }
61
+
62
+ export { Textarea };
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { useTranslator } from 'intor/react';
4
+ import 'react';
5
+ import 'ua-parser-js';
6
+ import { cn } from '../../../../applications/shadcn/utils.js';
7
+ import 'next/navigation';
8
+ import { NAVBAR_HEIGHT, PAGE_HEADER_HEIGHT } from '../../../styles/constants.js';
9
+
10
+ function ContentContainer({
11
+ className = "",
12
+ children,
13
+ isNotFound = false,
14
+ isFixHeight,
15
+ ...props
16
+ }) {
17
+ const { t } = useTranslator();
18
+ const ABOVE_HEIGHT = NAVBAR_HEIGHT + PAGE_HEADER_HEIGHT;
19
+ return /* @__PURE__ */ jsx(
20
+ "div",
21
+ {
22
+ style: {
23
+ height: isFixHeight ? `calc(100vh - ${ABOVE_HEIGHT}px)` : "auto"
24
+ },
25
+ className: cn(
26
+ className,
27
+ "relative",
28
+ "flex flex-col gap-4",
29
+ "px-6 pt-6",
30
+ isFixHeight ? "pb-6" : "flex-1 pb-64"
31
+ ),
32
+ ...props,
33
+ children: isNotFound ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("ui.no-data.text") }) : children
34
+ }
35
+ );
36
+ }
37
+
38
+ export { ContentContainer };
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { Link } from 'intor/next';
4
+ import { Languages } from 'lucide-react';
5
+ import '@radix-ui/react-avatar';
6
+ import 'react';
7
+ import 'ua-parser-js';
8
+ import 'clsx';
9
+ import 'tailwind-merge';
10
+ import 'next/navigation';
11
+ import '../../../shadcn/badge.js';
12
+ import '../../../shadcn/button.js';
13
+ import '@radix-ui/react-collapsible';
14
+ import '@radix-ui/react-dialog';
15
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '../../../shadcn/dropdown-menu.js';
16
+ import '../../../shadcn/input-group.js';
17
+ import '@radix-ui/react-label';
18
+ import '@radix-ui/react-select';
19
+ import '@radix-ui/react-separator';
20
+ import '../../../shadcn/sidebar.js';
21
+ import '@radix-ui/react-tooltip';
22
+ import { Button } from '../../buttons/button.js';
23
+ import 'intor/react';
24
+
25
+ function createI18nSelector({
26
+ enabled,
27
+ locales,
28
+ localeDisplay
29
+ }) {
30
+ return function I18nSelector() {
31
+ if (!enabled) return null;
32
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
33
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "icon", children: [
34
+ /* @__PURE__ */ jsx(Languages, {}),
35
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Switch Languages" })
36
+ ] }) }),
37
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", children: locales.map((locale) => /* @__PURE__ */ jsx(Link, { locale, children: /* @__PURE__ */ jsx(DropdownMenuItem, { children: localeDisplay[locale] }) }, locale)) })
38
+ ] });
39
+ };
40
+ }
41
+
42
+ export { createI18nSelector };
@@ -0,0 +1,106 @@
1
+ "use client";
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useTranslator } from 'intor/react';
4
+ import { UserCircle, ChevronsUpDown, PenLine } from 'lucide-react';
5
+ import Link from 'next/link';
6
+ import { PATHS } from '../../../../../../constants/paths/index.js';
7
+ import '../../../../../../constants/redirect-paths.js';
8
+ import 'mime-types';
9
+ import { findTranslation } from '../../../../../../shared/translation/find-translation.js';
10
+ import { joinUrl } from '../../../../../../shared/utils/join-url.js';
11
+ import { Avatar, AvatarImage, AvatarFallback } from '../../../shadcn/avatar.js';
12
+ import '../../../shadcn/badge.js';
13
+ import '../../../shadcn/button.js';
14
+ import 'react';
15
+ import 'ua-parser-js';
16
+ import 'clsx';
17
+ import 'tailwind-merge';
18
+ import 'next/navigation';
19
+ import '@radix-ui/react-collapsible';
20
+ import '@radix-ui/react-dialog';
21
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuItem } from '../../../shadcn/dropdown-menu.js';
22
+ import '../../../shadcn/input-group.js';
23
+ import '@radix-ui/react-label';
24
+ import '@radix-ui/react-select';
25
+ import '@radix-ui/react-separator';
26
+ import { SidebarMenu, SidebarMenuItem, SidebarMenuButton } from '../../../shadcn/sidebar.js';
27
+ import { Spinner } from '../../../shadcn/spinner.js';
28
+ import '@radix-ui/react-tooltip';
29
+ import { Button } from '../../buttons/button.js';
30
+
31
+ function NavUser({
32
+ storageUrl,
33
+ admin,
34
+ isLoading = false,
35
+ SignOutButton
36
+ }) {
37
+ const { t, locale } = useTranslator();
38
+ const { name } = findTranslation(admin?.translations, locale);
39
+ if (isLoading)
40
+ return /* @__PURE__ */ jsx(Button, { variant: "outline", size: "icon", disabled: true, className: "w-64", children: /* @__PURE__ */ jsx(Spinner, {}) });
41
+ if (!admin)
42
+ return /* @__PURE__ */ jsx(Button, { variant: "outline", size: "icon", disabled: true, className: "w-64", children: /* @__PURE__ */ jsx(UserCircle, { className: "size-4" }) });
43
+ return /* @__PURE__ */ jsx(SidebarMenu, { className: "w-64", children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
44
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
45
+ SidebarMenuButton,
46
+ {
47
+ size: "lg",
48
+ className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
49
+ disabled: isLoading,
50
+ children: [
51
+ /* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
52
+ admin.avatarImage?.key && /* @__PURE__ */ jsx(
53
+ AvatarImage,
54
+ {
55
+ src: joinUrl(storageUrl, admin.avatarImage?.key),
56
+ alt: name ?? ""
57
+ }
58
+ ),
59
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-lg" })
60
+ ] }),
61
+ /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
62
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: name }),
63
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs", children: admin.email })
64
+ ] }),
65
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-auto size-4" })
66
+ ]
67
+ }
68
+ ) }),
69
+ /* @__PURE__ */ jsxs(
70
+ DropdownMenuContent,
71
+ {
72
+ className: "w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg",
73
+ side: "bottom",
74
+ align: "end",
75
+ sideOffset: 4,
76
+ children: [
77
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
78
+ /* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
79
+ admin.avatarImage?.key && /* @__PURE__ */ jsx(
80
+ AvatarImage,
81
+ {
82
+ src: joinUrl(storageUrl, admin.avatarImage?.key),
83
+ alt: name ?? ""
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-lg" })
87
+ ] }),
88
+ /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
89
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: name }),
90
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs", children: admin.email })
91
+ ] })
92
+ ] }) }),
93
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
94
+ /* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(Link, { href: PATHS.auth.changePassword.path, children: /* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
95
+ /* @__PURE__ */ jsx(PenLine, {}),
96
+ t("auth.change-password.text")
97
+ ] }) }) }),
98
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
99
+ SignOutButton
100
+ ]
101
+ }
102
+ )
103
+ ] }) }) });
104
+ }
105
+
106
+ export { NavUser };
@@ -0,0 +1,84 @@
1
+ "use client";
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useTranslator } from 'intor/react';
4
+ import { SidebarIcon, House, SquareArrowOutUpRight } from 'lucide-react';
5
+ import { PATHS } from '../../../../../../constants/paths/index.js';
6
+ import '../../../../../../constants/redirect-paths.js';
7
+ import { useAdmin } from '../../../../../infrastructure/contexts/admin.js';
8
+ import 'next-themes';
9
+ import '@tanstack/react-query';
10
+ import 'react';
11
+ import 'mime-types';
12
+ import 'sonner';
13
+ import '@radix-ui/react-avatar';
14
+ import 'ua-parser-js';
15
+ import 'clsx';
16
+ import 'tailwind-merge';
17
+ import 'next/navigation';
18
+ import '../../../shadcn/badge.js';
19
+ import '../../../shadcn/button.js';
20
+ import '@radix-ui/react-collapsible';
21
+ import '@radix-ui/react-dialog';
22
+ import '@radix-ui/react-dropdown-menu';
23
+ import '../../../shadcn/input-group.js';
24
+ import '@radix-ui/react-label';
25
+ import '@radix-ui/react-select';
26
+ import { Separator } from '../../../shadcn/separator.js';
27
+ import { useSidebar } from '../../../shadcn/sidebar.js';
28
+ import '@radix-ui/react-tooltip';
29
+ import { Button } from '../../buttons/button.js';
30
+ import { NavUser } from './nav-user.js';
31
+ import { ThemeSelector } from './theme-selector.js';
32
+
33
+ function createNavbar({
34
+ webUrl,
35
+ storageUrl,
36
+ I18nSelector,
37
+ SignOutButton
38
+ }) {
39
+ return function Navbar() {
40
+ const { toggleSidebar } = useSidebar();
41
+ const { admin, isLoading } = useAdmin();
42
+ const { t } = useTranslator();
43
+ return /* @__PURE__ */ jsx("header", { className: "bg-background sticky top-0 z-50 flex w-full items-center border-b", children: /* @__PURE__ */ jsxs("div", { className: "flex h-(--header-height) w-full items-center gap-2 px-2", children: [
44
+ /* @__PURE__ */ jsx(
45
+ Button,
46
+ {
47
+ className: "h-8 w-8",
48
+ variant: "ghost",
49
+ size: "icon",
50
+ onClick: toggleSidebar,
51
+ children: /* @__PURE__ */ jsx(SidebarIcon, {})
52
+ }
53
+ ),
54
+ /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mr-1 h-4" }),
55
+ /* @__PURE__ */ jsx(
56
+ Button,
57
+ {
58
+ variant: "outline",
59
+ size: "icon",
60
+ href: PATHS.main.dashboard.path,
61
+ children: /* @__PURE__ */ jsx(House, {})
62
+ }
63
+ ),
64
+ /* @__PURE__ */ jsxs(Button, { variant: "outline", href: webUrl, openNewTab: true, children: [
65
+ /* @__PURE__ */ jsx(SquareArrowOutUpRight, {}),
66
+ t("ui.layout.navbar.website-homepage.text")
67
+ ] }),
68
+ /* @__PURE__ */ jsx("div", { className: "ml-auto" }),
69
+ /* @__PURE__ */ jsx(I18nSelector, {}),
70
+ /* @__PURE__ */ jsx(ThemeSelector, {}),
71
+ /* @__PURE__ */ jsx(
72
+ NavUser,
73
+ {
74
+ storageUrl,
75
+ SignOutButton: /* @__PURE__ */ jsx(SignOutButton, {}),
76
+ admin,
77
+ isLoading
78
+ }
79
+ )
80
+ ] }) });
81
+ };
82
+ }
83
+
84
+ export { createNavbar };
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useTranslator } from 'intor/react';
4
+ import { LogOut } from 'lucide-react';
5
+ import { useRouter } from 'next/navigation';
6
+ import { PATHS } from '../../../../../../constants/paths/index.js';
7
+ import '../../../../../../constants/redirect-paths.js';
8
+ import 'react';
9
+ import 'ua-parser-js';
10
+ import 'clsx';
11
+ import 'tailwind-merge';
12
+ import { isConfirm } from '../../../../../applications/ui/is-confirm.js';
13
+ import { useAdmin } from '../../../../../infrastructure/contexts/admin.js';
14
+ import 'next-themes';
15
+ import '@tanstack/react-query';
16
+ import 'mime-types';
17
+ import 'sonner';
18
+ import '@radix-ui/react-avatar';
19
+ import '../../../shadcn/badge.js';
20
+ import '../../../shadcn/button.js';
21
+ import '@radix-ui/react-collapsible';
22
+ import '@radix-ui/react-dialog';
23
+ import { DropdownMenuItem } from '../../../shadcn/dropdown-menu.js';
24
+ import '../../../shadcn/input-group.js';
25
+ import '@radix-ui/react-label';
26
+ import '@radix-ui/react-select';
27
+ import '@radix-ui/react-separator';
28
+ import '../../../shadcn/sidebar.js';
29
+ import { Spinner } from '../../../shadcn/spinner.js';
30
+ import '@radix-ui/react-tooltip';
31
+
32
+ function createSignOutButton({
33
+ useCommand,
34
+ signOutAction
35
+ }) {
36
+ return function SignOutButton() {
37
+ const { t } = useTranslator();
38
+ const router = useRouter();
39
+ const { setAdmin } = useAdmin();
40
+ const { execute, isRedirecting } = useCommand(signOutAction, {
41
+ onSuccess: () => {
42
+ setAdmin(null);
43
+ router.push(PATHS.auth.signIn.path);
44
+ }
45
+ });
46
+ const handleSignOut = () => {
47
+ if (!isConfirm(t)) return;
48
+ void execute();
49
+ };
50
+ const buttonText = isRedirecting ? /* @__PURE__ */ jsx(Spinner, {}) : t("auth.sign-out.text");
51
+ return /* @__PURE__ */ jsx("button", { onClick: handleSignOut, className: "w-full", children: /* @__PURE__ */ jsxs(DropdownMenuItem, { variant: "destructive", children: [
52
+ /* @__PURE__ */ jsx(LogOut, {}),
53
+ buttonText
54
+ ] }) });
55
+ };
56
+ }
57
+
58
+ export { createSignOutButton };