@s-hirano-ist/s-ui 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/display/loading.d.ts +14 -0
- package/dist/display/loading.d.ts.map +1 -1
- package/dist/display/loading.js +14 -0
- package/dist/display/loading.js.map +1 -1
- package/dist/display/status/status-code-view.d.ts +29 -2
- package/dist/display/status/status-code-view.d.ts.map +1 -1
- package/dist/display/status/status-code-view.js +18 -0
- package/dist/display/status/status-code-view.js.map +1 -1
- package/dist/forms/fields/form-dropdown-input.d.ts +61 -7
- package/dist/forms/fields/form-dropdown-input.d.ts.map +1 -1
- package/dist/forms/fields/form-dropdown-input.js +64 -11
- package/dist/forms/fields/form-dropdown-input.js.map +1 -1
- package/dist/forms/fields/form-file-input.d.ts +30 -3
- package/dist/forms/fields/form-file-input.d.ts.map +1 -1
- package/dist/forms/fields/form-file-input.js +21 -0
- package/dist/forms/fields/form-file-input.js.map +1 -1
- package/dist/forms/fields/form-input-with-button.d.ts +41 -3
- package/dist/forms/fields/form-input-with-button.d.ts.map +1 -1
- package/dist/forms/fields/form-input-with-button.js +28 -0
- package/dist/forms/fields/form-input-with-button.js.map +1 -1
- package/dist/forms/fields/form-input.d.ts +32 -3
- package/dist/forms/fields/form-input.d.ts.map +1 -1
- package/dist/forms/fields/form-input.js +23 -0
- package/dist/forms/fields/form-input.js.map +1 -1
- package/dist/forms/fields/form-textarea.d.ts +31 -3
- package/dist/forms/fields/form-textarea.d.ts.map +1 -1
- package/dist/forms/fields/form-textarea.js +22 -0
- package/dist/forms/fields/form-textarea.js.map +1 -1
- package/dist/forms/generic-form-wrapper.d.ts +66 -3
- package/dist/forms/generic-form-wrapper.d.ts.map +1 -1
- package/dist/forms/generic-form-wrapper.js +53 -0
- package/dist/forms/generic-form-wrapper.js.map +1 -1
- package/dist/hooks/use-infinite-scroll.d.ts +58 -3
- package/dist/hooks/use-infinite-scroll.d.ts.map +1 -1
- package/dist/hooks/use-infinite-scroll.js +40 -0
- package/dist/hooks/use-infinite-scroll.js.map +1 -1
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -1
- package/dist/layouts/body/viewer-body.d.ts +49 -3
- package/dist/layouts/body/viewer-body.d.ts.map +1 -1
- package/dist/layouts/body/viewer-body.js +41 -1
- package/dist/layouts/body/viewer-body.js.map +1 -1
- package/dist/providers/theme-provider.d.ts +23 -0
- package/dist/providers/theme-provider.d.ts.map +1 -1
- package/dist/providers/theme-provider.js +23 -0
- package/dist/providers/theme-provider.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/badge.d.ts +41 -0
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/badge.js +35 -0
- package/dist/ui/badge.js.map +1 -1
- package/dist/ui/button.d.ts +58 -0
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +50 -0
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.d.ts +74 -0
- package/dist/ui/card.d.ts.map +1 -1
- package/dist/ui/card.js +74 -0
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/command.d.ts +117 -1
- package/dist/ui/command.d.ts.map +1 -1
- package/dist/ui/command.js +117 -1
- package/dist/ui/command.js.map +1 -1
- package/dist/ui/dialog.d.ts +88 -0
- package/dist/ui/dialog.d.ts.map +1 -1
- package/dist/ui/dialog.js +88 -0
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/drawer.d.ts +85 -0
- package/dist/ui/drawer.d.ts.map +1 -1
- package/dist/ui/drawer.js +85 -0
- package/dist/ui/drawer.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts +88 -0
- package/dist/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/ui/dropdown-menu.js +88 -0
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/input.d.ts +27 -0
- package/dist/ui/input.d.ts.map +1 -1
- package/dist/ui/input.js +22 -0
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/label.d.ts +16 -0
- package/dist/ui/label.d.ts.map +1 -1
- package/dist/ui/label.js +20 -0
- package/dist/ui/label.js.map +1 -1
- package/dist/ui/popover.d.ts +50 -0
- package/dist/ui/popover.d.ts.map +1 -0
- package/dist/ui/popover.js +54 -0
- package/dist/ui/popover.js.map +1 -0
- package/dist/ui/sonner.d.ts +27 -0
- package/dist/ui/sonner.d.ts.map +1 -1
- package/dist/ui/sonner.js +22 -0
- package/dist/ui/sonner.js.map +1 -1
- package/dist/ui/tabs.d.ts +50 -0
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +50 -0
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/textarea.d.ts +24 -0
- package/dist/ui/textarea.d.ts.map +1 -1
- package/dist/ui/textarea.js +19 -0
- package/dist/ui/textarea.js.map +1 -1
- package/dist/utils/cn.d.ts +19 -0
- package/dist/utils/cn.d.ts.map +1 -1
- package/dist/utils/cn.js +19 -0
- package/dist/utils/cn.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,6 +2,28 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Label } from "../../ui/label";
|
|
3
3
|
import { Textarea } from "../../ui/textarea";
|
|
4
4
|
import { useFormValues } from "../generic-form-wrapper";
|
|
5
|
+
/**
|
|
6
|
+
* A labeled multi-line text input component for forms.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* Integrates with GenericFormWrapper for form state preservation.
|
|
10
|
+
* Automatically restores value on form errors.
|
|
11
|
+
*
|
|
12
|
+
* @param props - Textarea props including label and standard textarea attributes
|
|
13
|
+
* @returns A labeled textarea field
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <FormTextarea
|
|
18
|
+
* label="Description"
|
|
19
|
+
* htmlFor="description"
|
|
20
|
+
* name="description"
|
|
21
|
+
* rows={5}
|
|
22
|
+
* />
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @see {@link GenericFormWrapper} for form integration
|
|
26
|
+
*/
|
|
5
27
|
export function FormTextarea({ label, htmlFor, defaultValue, ...textareaProps }) {
|
|
6
28
|
const formValues = useFormValues();
|
|
7
29
|
const preservedValue = formValues[textareaProps.name || htmlFor];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-textarea.js","sourceRoot":"","sources":["../../../forms/fields/form-textarea.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"form-textarea.js","sourceRoot":"","sources":["../../../forms/fields/form-textarea.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAcxD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,YAAY,CAAC,EAC5B,KAAK,EACL,OAAO,EACP,YAAY,EACZ,GAAG,aAAa,EACG;IACnB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,cAAc,GAAG,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC;IAEjE,OAAO,CACN,eAAK,SAAS,EAAC,WAAW,aACzB,KAAC,KAAK,IAAC,OAAO,EAAE,OAAO,YAAG,KAAK,GAAS,EACxC,KAAC,QAAQ,IACR,YAAY,EAAE,cAAc,IAAI,YAAY,EAC5C,EAAE,EAAE,OAAO,KACP,aAAa,GAChB,IACG,CACN,CAAC;AACH,CAAC"}
|
|
@@ -1,18 +1,81 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Hook to access form values from the GenericFormWrapper context.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Use this hook in form field components to access preserved form values
|
|
7
|
+
* when a form submission fails and values need to be restored.
|
|
8
|
+
*
|
|
9
|
+
* @returns Record of field names to their preserved values
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* function MyFormField({ name }) {
|
|
14
|
+
* const formValues = useFormValues();
|
|
15
|
+
* const preservedValue = formValues[name];
|
|
16
|
+
* return <input defaultValue={preservedValue} name={name} />;
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @see {@link GenericFormWrapper} for the provider component
|
|
21
|
+
*/
|
|
2
22
|
export declare const useFormValues: () => Record<string, string>;
|
|
3
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Props for the GenericFormWrapper component.
|
|
25
|
+
*
|
|
26
|
+
* @typeParam T - The response type from the form action
|
|
27
|
+
*
|
|
28
|
+
* @see {@link GenericFormWrapper} for the component
|
|
29
|
+
*/
|
|
30
|
+
export type GenericFormWrapperProps<T> = {
|
|
31
|
+
/** Server action to handle form submission */
|
|
4
32
|
action: (formData: FormData) => Promise<T>;
|
|
33
|
+
/** Form field components */
|
|
5
34
|
children: ReactNode;
|
|
35
|
+
/** Label for the save button (fallback) */
|
|
6
36
|
saveLabel: string;
|
|
37
|
+
/** Label for the submit button */
|
|
7
38
|
submitLabel?: string;
|
|
39
|
+
/** Label shown during loading state */
|
|
8
40
|
loadingLabel?: string;
|
|
41
|
+
/** Optional custom submit handler */
|
|
9
42
|
onSubmit?: (formData: FormData) => Promise<void>;
|
|
43
|
+
/** Pre-filled form values */
|
|
10
44
|
preservedValues?: Record<string, string>;
|
|
45
|
+
/** Callback after form submission with response message */
|
|
11
46
|
afterSubmit: (responseMessage: string) => void;
|
|
12
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* A generic form wrapper with server action integration.
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
52
|
+
* Provides a consistent form experience with:
|
|
53
|
+
* - Server action integration via useActionState
|
|
54
|
+
* - Loading state with spinner
|
|
55
|
+
* - Form value preservation on error
|
|
56
|
+
* - Context-based form state sharing
|
|
57
|
+
*
|
|
58
|
+
* @typeParam T - Response type with `message` and `success` properties
|
|
59
|
+
* @param props - Form wrapper configuration
|
|
60
|
+
* @returns A form with submit handling and loading states
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <GenericFormWrapper
|
|
65
|
+
* action={createArticle}
|
|
66
|
+
* saveLabel="Save"
|
|
67
|
+
* submitLabel="Create Article"
|
|
68
|
+
* afterSubmit={(msg) => toast(msg)}
|
|
69
|
+
* >
|
|
70
|
+
* <FormInput label="Title" htmlFor="title" name="title" />
|
|
71
|
+
* <FormTextarea label="Content" htmlFor="content" name="content" />
|
|
72
|
+
* </GenericFormWrapper>
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @see {@link useFormValues} for accessing form state in child components
|
|
76
|
+
*/
|
|
13
77
|
export declare function GenericFormWrapper<T extends {
|
|
14
78
|
message: string;
|
|
15
79
|
success: boolean;
|
|
16
|
-
}>({ action, children, saveLabel, submitLabel, loadingLabel, onSubmit, preservedValues, afterSubmit, }:
|
|
17
|
-
export {};
|
|
80
|
+
}>({ action, children, saveLabel, submitLabel, loadingLabel, onSubmit, preservedValues, afterSubmit, }: GenericFormWrapperProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
18
81
|
//# sourceMappingURL=generic-form-wrapper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-form-wrapper.d.ts","sourceRoot":"","sources":["../../forms/generic-form-wrapper.tsx"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,SAAS,EAKd,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"generic-form-wrapper.d.ts","sourceRoot":"","sources":["../../forms/generic-form-wrapper.tsx"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,SAAS,EAKd,MAAM,OAAO,CAAC;AAUf;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,8BAAsC,CAAC;AAEjE;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI;IACxC,8CAA8C;IAC9C,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3C,4BAA4B;IAC5B,QAAQ,EAAE,SAAS,CAAC;IACpB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,6BAA6B;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,2DAA2D;IAC3D,WAAW,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CACjC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAC9C,EACD,MAAM,EACN,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,WAAW,GACX,EAAE,uBAAuB,CAAC,CAAC,CAAC,2CAkD5B"}
|
|
@@ -3,8 +3,61 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { createContext, useActionState, useContext, useEffect, useState, } from "react";
|
|
4
4
|
import Loading from "../display/loading";
|
|
5
5
|
import { Button } from "../ui/button";
|
|
6
|
+
/**
|
|
7
|
+
* Context for sharing form values across form fields.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
6
10
|
const FormValuesContext = createContext({});
|
|
11
|
+
/**
|
|
12
|
+
* Hook to access form values from the GenericFormWrapper context.
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* Use this hook in form field components to access preserved form values
|
|
16
|
+
* when a form submission fails and values need to be restored.
|
|
17
|
+
*
|
|
18
|
+
* @returns Record of field names to their preserved values
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* function MyFormField({ name }) {
|
|
23
|
+
* const formValues = useFormValues();
|
|
24
|
+
* const preservedValue = formValues[name];
|
|
25
|
+
* return <input defaultValue={preservedValue} name={name} />;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @see {@link GenericFormWrapper} for the provider component
|
|
30
|
+
*/
|
|
7
31
|
export const useFormValues = () => useContext(FormValuesContext);
|
|
32
|
+
/**
|
|
33
|
+
* A generic form wrapper with server action integration.
|
|
34
|
+
*
|
|
35
|
+
* @remarks
|
|
36
|
+
* Provides a consistent form experience with:
|
|
37
|
+
* - Server action integration via useActionState
|
|
38
|
+
* - Loading state with spinner
|
|
39
|
+
* - Form value preservation on error
|
|
40
|
+
* - Context-based form state sharing
|
|
41
|
+
*
|
|
42
|
+
* @typeParam T - Response type with `message` and `success` properties
|
|
43
|
+
* @param props - Form wrapper configuration
|
|
44
|
+
* @returns A form with submit handling and loading states
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <GenericFormWrapper
|
|
49
|
+
* action={createArticle}
|
|
50
|
+
* saveLabel="Save"
|
|
51
|
+
* submitLabel="Create Article"
|
|
52
|
+
* afterSubmit={(msg) => toast(msg)}
|
|
53
|
+
* >
|
|
54
|
+
* <FormInput label="Title" htmlFor="title" name="title" />
|
|
55
|
+
* <FormTextarea label="Content" htmlFor="content" name="content" />
|
|
56
|
+
* </GenericFormWrapper>
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @see {@link useFormValues} for accessing form state in child components
|
|
60
|
+
*/
|
|
8
61
|
export function GenericFormWrapper({ action, children, saveLabel, submitLabel, loadingLabel, onSubmit, preservedValues, afterSubmit, }) {
|
|
9
62
|
const [formValues, setFormValues] = useState(preservedValues || {});
|
|
10
63
|
useEffect(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-form-wrapper.js","sourceRoot":"","sources":["../../forms/generic-form-wrapper.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,OAAO,EACN,aAAa,EAEb,cAAc,EACd,UAAU,EACV,SAAS,EACT,QAAQ,GACR,MAAM,OAAO,CAAC;AACf,OAAO,OAAO,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,iBAAiB,GAAG,aAAa,CAAyB,EAAE,CAAC,CAAC;AAEpE,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"generic-form-wrapper.js","sourceRoot":"","sources":["../../forms/generic-form-wrapper.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,OAAO,EACN,aAAa,EAEb,cAAc,EACd,UAAU,EACV,SAAS,EACT,QAAQ,GACR,MAAM,OAAO,CAAC;AACf,OAAO,OAAO,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;GAGG;AACH,MAAM,iBAAiB,GAAG,aAAa,CAAyB,EAAE,CAAC,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AA4BjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,kBAAkB,CAEhC,EACD,MAAM,EACN,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,WAAW,GACiB;IAC5B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAC3C,eAAe,IAAI,EAAE,CACrB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,eAAe,EAAE,CAAC;YACrB,aAAa,CAAC,eAAe,CAAC,CAAC;QAChC,CAAC;IACF,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,MAAM,UAAU,GAAG,KAAK,EACvB,cAAwB,EACxB,QAAkB,EACE,EAAE;QACtB,IAAI,QAAQ,EAAE,CAAC;YACd,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACzB,OAAO,IAAI,CAAC;QACb,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAE9B,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,wBAAwB;YACxB,aAAa,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,QAAQ,CAAC;QACjB,CAAC;QACD,8BAA8B;QAC9B,IAAI,UAAU,IAAI,QAAQ,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACjD,aAAa,CAAC,QAAQ,CAAC,QAAkC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEtE,OAAO,CACN,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU,YAC5C,gBAAM,MAAM,EAAE,YAAY,EAAE,SAAS,EAAC,qBAAqB,aACzD,SAAS,CAAC,CAAC,CAAC,KAAC,OAAO,KAAG,CAAC,CAAC,CAAC,QAAQ,EACnC,KAAC,MAAM,IAAC,SAAS,EAAC,QAAQ,EAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAC,QAAQ,YAC3D,SAAS,IAAI,YAAY;wBACzB,CAAC,CAAC,YAAY;wBACd,CAAC,CAAC,WAAW;4BACZ,CAAC,CAAC,WAAW;4BACb,CAAC,CAAC,SAAS,GACL,IACH,GACqB,CAC7B,CAAC;AACH,CAAC"}
|
|
@@ -1,13 +1,68 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Options for the useInfiniteScroll hook.
|
|
3
|
+
*
|
|
4
|
+
* @see {@link useInfiniteScroll} for the hook
|
|
5
|
+
*/
|
|
6
|
+
export type UseInfiniteScrollOptions = {
|
|
7
|
+
/** Whether there are more pages to load */
|
|
2
8
|
hasNextPage: boolean;
|
|
9
|
+
/** Whether a page is currently being fetched */
|
|
3
10
|
isFetchingNextPage: boolean;
|
|
11
|
+
/** Function to fetch the next page */
|
|
4
12
|
fetchNextPage: () => Promise<void>;
|
|
13
|
+
/** Margin around the root for intersection detection */
|
|
5
14
|
rootMargin?: string;
|
|
15
|
+
/** Visibility threshold for triggering intersection */
|
|
6
16
|
threshold?: number;
|
|
7
17
|
};
|
|
8
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Return value from the useInfiniteScroll hook.
|
|
20
|
+
*
|
|
21
|
+
* @see {@link useInfiniteScroll} for the hook
|
|
22
|
+
*/
|
|
23
|
+
export type UseInfiniteScrollReturn = {
|
|
24
|
+
/** Ref callback to attach to the last element */
|
|
9
25
|
lastElementRef: (node: HTMLElement | null) => void;
|
|
10
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* Hook for implementing infinite scroll with Intersection Observer.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* Automatically loads more content when the last element becomes visible.
|
|
32
|
+
* Uses IntersectionObserver for efficient scroll detection.
|
|
33
|
+
*
|
|
34
|
+
* Features:
|
|
35
|
+
* - Automatic fetch when last element is visible
|
|
36
|
+
* - Prevents duplicate fetches during loading
|
|
37
|
+
* - SSR-safe with delayed initialization
|
|
38
|
+
* - Configurable root margin and threshold
|
|
39
|
+
*
|
|
40
|
+
* @param options - Configuration for pagination and intersection
|
|
41
|
+
* @returns Object containing ref callback for the last element
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function ItemList({ items, hasMore, fetchMore }) {
|
|
46
|
+
* const { lastElementRef } = useInfiniteScroll({
|
|
47
|
+
* hasNextPage: hasMore,
|
|
48
|
+
* isFetchingNextPage: false,
|
|
49
|
+
* fetchNextPage: fetchMore,
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* return (
|
|
53
|
+
* <ul>
|
|
54
|
+
* {items.map((item, i) => (
|
|
55
|
+
* <li
|
|
56
|
+
* key={item.id}
|
|
57
|
+
* ref={i === items.length - 1 ? lastElementRef : null}
|
|
58
|
+
* >
|
|
59
|
+
* {item.name}
|
|
60
|
+
* </li>
|
|
61
|
+
* ))}
|
|
62
|
+
* </ul>
|
|
63
|
+
* );
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
11
67
|
export declare function useInfiniteScroll({ hasNextPage, isFetchingNextPage, fetchNextPage, rootMargin, threshold, }: UseInfiniteScrollOptions): UseInfiniteScrollReturn;
|
|
12
|
-
export {};
|
|
13
68
|
//# sourceMappingURL=use-infinite-scroll.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-infinite-scroll.d.ts","sourceRoot":"","sources":["../../hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAIA,
|
|
1
|
+
{"version":3,"file":"use-infinite-scroll.d.ts","sourceRoot":"","sources":["../../hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACtC,2CAA2C;IAC3C,WAAW,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,kBAAkB,EAAE,OAAO,CAAC;IAC5B,sCAAsC;IACtC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACrC,iDAAiD;IACjD,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CACnD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,iBAAiB,CAAC,EACjC,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,UAAoB,EACpB,SAAe,GACf,EAAE,wBAAwB,GAAG,uBAAuB,CAuCpD"}
|
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Hook for implementing infinite scroll with Intersection Observer.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Automatically loads more content when the last element becomes visible.
|
|
8
|
+
* Uses IntersectionObserver for efficient scroll detection.
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Automatic fetch when last element is visible
|
|
12
|
+
* - Prevents duplicate fetches during loading
|
|
13
|
+
* - SSR-safe with delayed initialization
|
|
14
|
+
* - Configurable root margin and threshold
|
|
15
|
+
*
|
|
16
|
+
* @param options - Configuration for pagination and intersection
|
|
17
|
+
* @returns Object containing ref callback for the last element
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* function ItemList({ items, hasMore, fetchMore }) {
|
|
22
|
+
* const { lastElementRef } = useInfiniteScroll({
|
|
23
|
+
* hasNextPage: hasMore,
|
|
24
|
+
* isFetchingNextPage: false,
|
|
25
|
+
* fetchNextPage: fetchMore,
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* return (
|
|
29
|
+
* <ul>
|
|
30
|
+
* {items.map((item, i) => (
|
|
31
|
+
* <li
|
|
32
|
+
* key={item.id}
|
|
33
|
+
* ref={i === items.length - 1 ? lastElementRef : null}
|
|
34
|
+
* >
|
|
35
|
+
* {item.name}
|
|
36
|
+
* </li>
|
|
37
|
+
* ))}
|
|
38
|
+
* </ul>
|
|
39
|
+
* );
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
3
43
|
export function useInfiniteScroll({ hasNextPage, isFetchingNextPage, fetchNextPage, rootMargin = "100px", threshold = 0.1, }) {
|
|
4
44
|
const observer = useRef(null);
|
|
5
45
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-infinite-scroll.js","sourceRoot":"","sources":["../../hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"use-infinite-scroll.js","sourceRoot":"","sources":["../../hooks/use-infinite-scroll.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA8BjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,iBAAiB,CAAC,EACjC,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,UAAU,GAAG,OAAO,EACpB,SAAS,GAAG,GAAG,GACW;IAC1B,MAAM,QAAQ,GAAG,MAAM,CAA8B,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1D,MAAM,cAAc,GAAG,WAAW,CACjC,CAAC,IAAwB,EAAE,EAAE;QAC5B,IAAI,kBAAkB;YAAE,OAAO;QAC/B,IAAI,QAAQ,CAAC,OAAO;YAAE,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAEpD,QAAQ,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAC1C,CAAC,OAAO,EAAE,EAAE;YACX,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,IAAI,WAAW,IAAI,aAAa,EAAE,CAAC;gBAChE,aAAa,EAAE,CAAC;YACjB,CAAC;QACF,CAAC,EACD;YACC,UAAU;YACV,SAAS;SACT,CACD,CAAC;QAEF,IAAI,IAAI;YAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,EACD;QACC,kBAAkB;QAClB,WAAW;QACX,aAAa;QACb,UAAU;QACV,SAAS;QACT,aAAa;KACb,CACD,CAAC;IAEF,oDAAoD;IACpD,SAAS,CAAC,GAAG,EAAE;QACd,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,cAAc,EAAE,CAAC;AAC3B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* UI component library for the content management system.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* This package provides reusable React components built with:
|
|
8
|
+
* - Radix UI primitives for accessibility
|
|
9
|
+
* - Tailwind CSS for styling
|
|
10
|
+
* - class-variance-authority for variant management
|
|
11
|
+
*
|
|
12
|
+
* ## Component Categories
|
|
13
|
+
*
|
|
14
|
+
* - **UI Components** - Base components (Button, Card, Input, Dialog, etc.)
|
|
15
|
+
* - **Form Components** - Form wrappers and field components
|
|
16
|
+
* - **Display Components** - Loading states and status displays
|
|
17
|
+
* - **Layout Components** - Markdown viewer and content layouts
|
|
18
|
+
* - **Hooks** - Custom React hooks (useInfiniteScroll)
|
|
19
|
+
* - **Providers** - Theme provider for dark/light mode
|
|
20
|
+
* - **Utilities** - cn() class merging utility
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* import { Button, Card, Input, Toaster } from "@s-hirano-ist/s-ui";
|
|
25
|
+
*
|
|
26
|
+
* function MyComponent() {
|
|
27
|
+
* return (
|
|
28
|
+
* <Card>
|
|
29
|
+
* <Input placeholder="Enter text..." />
|
|
30
|
+
* <Button>Submit</Button>
|
|
31
|
+
* <Toaster />
|
|
32
|
+
* </Card>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
1
37
|
export * from "./display/loading";
|
|
2
38
|
export * from "./display/status/status-code-view";
|
|
3
39
|
export * from "./forms/fields/form-dropdown-input";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAKH,cAAc,mBAAmB,CAAC;AAClC,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAE7C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,6BAA6B,CAAC;AAE5C,cAAc,4BAA4B,CAAC;AAE3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAG9B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* UI component library for the content management system.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* This package provides reusable React components built with:
|
|
8
|
+
* - Radix UI primitives for accessibility
|
|
9
|
+
* - Tailwind CSS for styling
|
|
10
|
+
* - class-variance-authority for variant management
|
|
11
|
+
*
|
|
12
|
+
* ## Component Categories
|
|
13
|
+
*
|
|
14
|
+
* - **UI Components** - Base components (Button, Card, Input, Dialog, etc.)
|
|
15
|
+
* - **Form Components** - Form wrappers and field components
|
|
16
|
+
* - **Display Components** - Loading states and status displays
|
|
17
|
+
* - **Layout Components** - Markdown viewer and content layouts
|
|
18
|
+
* - **Hooks** - Custom React hooks (useInfiniteScroll)
|
|
19
|
+
* - **Providers** - Theme provider for dark/light mode
|
|
20
|
+
* - **Utilities** - cn() class merging utility
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* import { Button, Card, Input, Toaster } from "@s-hirano-ist/s-ui";
|
|
25
|
+
*
|
|
26
|
+
* function MyComponent() {
|
|
27
|
+
* return (
|
|
28
|
+
* <Card>
|
|
29
|
+
* <Input placeholder="Enter text..." />
|
|
30
|
+
* <Button>Submit</Button>
|
|
31
|
+
* <Toaster />
|
|
32
|
+
* </Card>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
1
37
|
// UI Components
|
|
2
38
|
// Display Components
|
|
3
39
|
export * from "./display/loading";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAEhB,qBAAqB;AACrB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,kBAAkB;AAClB,cAAc,8BAA8B,CAAC;AAC7C,QAAQ;AACR,cAAc,6BAA6B,CAAC;AAC5C,oBAAoB;AACpB,cAAc,4BAA4B,CAAC;AAC3C,YAAY;AACZ,cAAc,4BAA4B,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAE9B,YAAY;AACZ,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,gBAAgB;AAEhB,qBAAqB;AACrB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,kBAAkB;AAClB,cAAc,8BAA8B,CAAC;AAC7C,QAAQ;AACR,cAAc,6BAA6B,CAAC;AAC5C,oBAAoB;AACpB,cAAc,4BAA4B,CAAC;AAC3C,YAAY;AACZ,cAAc,4BAA4B,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAE9B,YAAY;AACZ,cAAc,YAAY,CAAC"}
|
|
@@ -1,9 +1,55 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Props for the ViewerBodyClient component.
|
|
4
|
+
*
|
|
5
|
+
* @see {@link ViewerBodyClient} for the component
|
|
6
|
+
*/
|
|
7
|
+
export type ViewerBodyProps = {
|
|
8
|
+
/** Optional children to render before the markdown content */
|
|
3
9
|
children?: ReactNode;
|
|
10
|
+
/** Markdown content to render */
|
|
4
11
|
markdown: string;
|
|
5
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Converts markdown to React elements with syntax highlighting.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* Features:
|
|
18
|
+
* - GitHub Flavored Markdown (GFM) support
|
|
19
|
+
* - Syntax highlighting with VS Code Dark+ theme
|
|
20
|
+
* - Auto-generated heading IDs for anchor links
|
|
21
|
+
* - External link handling with nofollow/noreferrer
|
|
22
|
+
*
|
|
23
|
+
* @param markdown - The markdown string to convert
|
|
24
|
+
* @returns React elements representing the markdown
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* const content = await markdownToReact("# Hello\n\nWorld");
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
6
31
|
export declare function markdownToReact(markdown: string): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
7
|
-
|
|
8
|
-
|
|
32
|
+
/**
|
|
33
|
+
* A markdown viewer component with prose styling.
|
|
34
|
+
*
|
|
35
|
+
* @remarks
|
|
36
|
+
* Server component that renders markdown content with:
|
|
37
|
+
* - Prose typography from Tailwind CSS
|
|
38
|
+
* - Dark mode support
|
|
39
|
+
* - Responsive container width
|
|
40
|
+
* - Optional children rendered before content
|
|
41
|
+
*
|
|
42
|
+
* @param props - Markdown content and optional children
|
|
43
|
+
* @returns A styled markdown viewer
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <ViewerBodyClient markdown={noteContent}>
|
|
48
|
+
* <h1>Note Title</h1>
|
|
49
|
+
* </ViewerBodyClient>
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @see {@link markdownToReact} for the markdown conversion function
|
|
53
|
+
*/
|
|
54
|
+
export declare function ViewerBodyClient({ children, markdown, }: ViewerBodyProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
9
55
|
//# sourceMappingURL=viewer-body.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewer-body.d.ts","sourceRoot":"","sources":["../../../layouts/body/viewer-body.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,
|
|
1
|
+
{"version":3,"file":"viewer-body.d.ts","sourceRoot":"","sources":["../../../layouts/body/viewer-body.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,oDAsDrD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,gBAAgB,CAAC,EACtC,QAAQ,EACR,QAAQ,GACR,EAAE,eAAe,oDASjB"}
|
|
@@ -3,6 +3,24 @@ import ReactMarkdown from "react-markdown";
|
|
|
3
3
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
|
4
4
|
import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
6
|
+
/**
|
|
7
|
+
* Converts markdown to React elements with syntax highlighting.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Features:
|
|
11
|
+
* - GitHub Flavored Markdown (GFM) support
|
|
12
|
+
* - Syntax highlighting with VS Code Dark+ theme
|
|
13
|
+
* - Auto-generated heading IDs for anchor links
|
|
14
|
+
* - External link handling with nofollow/noreferrer
|
|
15
|
+
*
|
|
16
|
+
* @param markdown - The markdown string to convert
|
|
17
|
+
* @returns React elements representing the markdown
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* const content = await markdownToReact("# Hello\n\nWorld");
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
6
24
|
export async function markdownToReact(markdown) {
|
|
7
25
|
const components = {
|
|
8
26
|
code({ className, children }) {
|
|
@@ -38,7 +56,29 @@ export async function markdownToReact(markdown) {
|
|
|
38
56
|
};
|
|
39
57
|
return (_jsx(ReactMarkdown, { components: components, remarkPlugins: [remarkGfm], children: markdown }));
|
|
40
58
|
}
|
|
41
|
-
|
|
59
|
+
/**
|
|
60
|
+
* A markdown viewer component with prose styling.
|
|
61
|
+
*
|
|
62
|
+
* @remarks
|
|
63
|
+
* Server component that renders markdown content with:
|
|
64
|
+
* - Prose typography from Tailwind CSS
|
|
65
|
+
* - Dark mode support
|
|
66
|
+
* - Responsive container width
|
|
67
|
+
* - Optional children rendered before content
|
|
68
|
+
*
|
|
69
|
+
* @param props - Markdown content and optional children
|
|
70
|
+
* @returns A styled markdown viewer
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```tsx
|
|
74
|
+
* <ViewerBodyClient markdown={noteContent}>
|
|
75
|
+
* <h1>Note Title</h1>
|
|
76
|
+
* </ViewerBodyClient>
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @see {@link markdownToReact} for the markdown conversion function
|
|
80
|
+
*/
|
|
81
|
+
export async function ViewerBodyClient({ children, markdown, }) {
|
|
42
82
|
const content = await markdownToReact(markdown);
|
|
43
83
|
return (_jsxs("div", { className: "prose prose-sm dark:prose-invert mx-auto max-w-5xl space-y-8 px-4 py-2", children: [children, content] }));
|
|
44
84
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewer-body.js","sourceRoot":"","sources":["../../../layouts/body/viewer-body.tsx"],"names":[],"mappings":";AAEA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,KAAK,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,gDAAgD,CAAC;AAC7E,OAAO,SAAS,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"viewer-body.js","sourceRoot":"","sources":["../../../layouts/body/viewer-body.tsx"],"names":[],"mappings":";AAEA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,KAAK,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,gDAAgD,CAAC;AAC7E,OAAO,SAAS,MAAM,YAAY,CAAC;AAcnC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACrD,MAAM,UAAU,GAAe;QAC9B,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;YAC3B,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC;YAExB,OAAO,QAAQ,CAAC,CAAC,CAAC,CACjB,eAAM,SAAS,EAAE,SAAS,YAAG,QAAQ,GAAQ,CAC7C,CAAC,CAAC,CAAC,CACH,KAAC,iBAAiB,IAAC,MAAM,EAAC,KAAK,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,YACpE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GACjB,CACpB,CAAC;QACH,CAAC;QACD,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE;YACnB,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;YAC5C,OAAO,CACN,YACC,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,EACnD,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,YAExC,QAAQ,GACN,CACJ,CAAC;QACH,CAAC;QACD,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpB,MAAM,EAAE,GAAG,QAAQ;gBAClB,EAAE,QAAQ,EAAE;iBACX,WAAW,EAAE;iBACb,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC1B,OAAO,aAAI,EAAE,EAAE,EAAE,YAAG,QAAQ,GAAM,CAAC;QACpC,CAAC;QACD,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpB,MAAM,EAAE,GAAG,QAAQ;gBAClB,EAAE,QAAQ,EAAE;iBACX,WAAW,EAAE;iBACb,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC1B,OAAO,aAAI,EAAE,EAAE,EAAE,YAAG,QAAQ,GAAM,CAAC;QACpC,CAAC;QACD,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpB,MAAM,EAAE,GAAG,QAAQ;gBAClB,EAAE,QAAQ,EAAE;iBACX,WAAW,EAAE;iBACb,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC1B,OAAO,aAAI,EAAE,EAAE,EAAE,YAAG,QAAQ,GAAM,CAAC;QACpC,CAAC;KACD,CAAC;IAEF,OAAO,CACN,KAAC,aAAa,IAAC,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,SAAS,CAAC,YAC/D,QAAQ,GACM,CAChB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACtC,QAAQ,EACR,QAAQ,GACS;IACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEhD,OAAO,CACN,eAAK,SAAS,EAAC,wEAAwE,aACrF,QAAQ,EACR,OAAO,IACH,CACN,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
|
2
2
|
import type * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Theme provider component for dark/light mode support.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Wrapper around next-themes ThemeProvider.
|
|
8
|
+
* Enables theme switching and system theme detection.
|
|
9
|
+
*
|
|
10
|
+
* @param props - next-themes provider props
|
|
11
|
+
* @returns A theme context provider
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* // In your root layout
|
|
16
|
+
* <ThemeProvider
|
|
17
|
+
* attribute="class"
|
|
18
|
+
* defaultTheme="system"
|
|
19
|
+
* enableSystem
|
|
20
|
+
* disableTransitionOnChange
|
|
21
|
+
* >
|
|
22
|
+
* {children}
|
|
23
|
+
* </ThemeProvider>
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
3
26
|
export declare function ThemeProvider({ children, ...props }: React.ComponentProps<typeof NextThemesProvider>): import("react/jsx-runtime").JSX.Element;
|
|
4
27
|
//# sourceMappingURL=theme-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../providers/theme-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,wBAAgB,aAAa,CAAC,EAC7B,QAAQ,EACR,GAAG,KAAK,EACR,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,2CAEjD"}
|
|
1
|
+
{"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../providers/theme-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAAC,EAC7B,QAAQ,EACR,GAAG,KAAK,EACR,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,2CAEjD"}
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
|
4
|
+
/**
|
|
5
|
+
* Theme provider component for dark/light mode support.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Wrapper around next-themes ThemeProvider.
|
|
9
|
+
* Enables theme switching and system theme detection.
|
|
10
|
+
*
|
|
11
|
+
* @param props - next-themes provider props
|
|
12
|
+
* @returns A theme context provider
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // In your root layout
|
|
17
|
+
* <ThemeProvider
|
|
18
|
+
* attribute="class"
|
|
19
|
+
* defaultTheme="system"
|
|
20
|
+
* enableSystem
|
|
21
|
+
* disableTransitionOnChange
|
|
22
|
+
* >
|
|
23
|
+
* {children}
|
|
24
|
+
* </ThemeProvider>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
4
27
|
export function ThemeProvider({ children, ...props }) {
|
|
5
28
|
return _jsx(NextThemesProvider, { ...props, children: children });
|
|
6
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider.js","sourceRoot":"","sources":["../../providers/theme-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGlE,MAAM,UAAU,aAAa,CAAC,EAC7B,QAAQ,EACR,GAAG,KAAK,EACyC;IACjD,OAAO,KAAC,kBAAkB,OAAK,KAAK,YAAG,QAAQ,GAAsB,CAAC;AACvE,CAAC"}
|
|
1
|
+
{"version":3,"file":"theme-provider.js","sourceRoot":"","sources":["../../providers/theme-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAAC,EAC7B,QAAQ,EACR,GAAG,KAAK,EACyC;IACjD,OAAO,KAAC,kBAAkB,OAAK,KAAK,YAAG,QAAQ,GAAsB,CAAC;AACvE,CAAC"}
|