torch-glare 2.4.0 → 2.4.1
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/README.md +8 -0
- package/apps/lib/components/ActionButton.tsx +7 -12
- package/apps/lib/components/ActionsGroup.tsx +4 -15
- package/apps/lib/components/AlertDialog.tsx +173 -191
- package/apps/lib/components/Avatar.tsx +13 -16
- package/apps/lib/components/Badge.tsx +1 -3
- package/apps/lib/components/BadgeField.tsx +76 -71
- package/apps/lib/components/Breadcrumb.tsx +49 -85
- package/apps/lib/components/Button.tsx +20 -19
- package/apps/lib/components/ButtonGroup.tsx +31 -41
- package/apps/lib/components/Calendar.tsx +51 -29
- package/apps/lib/components/Card.tsx +2 -13
- package/apps/lib/components/ChartBlockTool.ts +17 -52
- package/apps/lib/components/Checkbox.tsx +9 -16
- package/apps/lib/components/ContextMenu.tsx +97 -96
- package/apps/lib/components/CountBadge.tsx +4 -6
- package/apps/lib/components/DataTable.tsx +196 -216
- package/apps/lib/components/DataViews/DataViewRadio.tsx +1 -6
- package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +13 -47
- package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
- package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
- package/apps/lib/components/DataViews/FilterPanel.tsx +155 -149
- package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
- package/apps/lib/components/DataViews/InboxView.tsx +22 -68
- package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
- package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
- package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
- package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
- package/apps/lib/components/DataViews/TableView.tsx +8 -28
- package/apps/lib/components/DataViews/TreeView.tsx +12 -40
- package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
- package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
- package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +30 -23
- package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
- package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
- package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
- package/apps/lib/components/DataViews/index.ts +26 -26
- package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
- package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
- package/apps/lib/components/DataViews/types.ts +104 -115
- package/apps/lib/components/DatePicker.tsx +198 -196
- package/apps/lib/components/Dialog.tsx +92 -105
- package/apps/lib/components/Divider.tsx +21 -24
- package/apps/lib/components/Drawer.tsx +79 -139
- package/apps/lib/components/DropdownMenu.tsx +131 -171
- package/apps/lib/components/FieldHint.tsx +4 -11
- package/apps/lib/components/Form.tsx +146 -155
- package/apps/lib/components/FormStepper.tsx +9 -39
- package/apps/lib/components/HeaderBar.tsx +1 -9
- package/apps/lib/components/ImageAttachment.tsx +111 -73
- package/apps/lib/components/InnerLabelField.tsx +20 -16
- package/apps/lib/components/Input.tsx +171 -172
- package/apps/lib/components/InputField.tsx +44 -45
- package/apps/lib/components/InputOTP.tsx +68 -69
- package/apps/lib/components/Label.tsx +31 -35
- package/apps/lib/components/LabelField.tsx +4 -5
- package/apps/lib/components/LabeledCheckBox.tsx +8 -12
- package/apps/lib/components/LabeledRadio.tsx +7 -5
- package/apps/lib/components/LinkButton.tsx +2 -9
- package/apps/lib/components/LoginButton.tsx +4 -9
- package/apps/lib/components/PasswordLevel.tsx +5 -5
- package/apps/lib/components/Popover.tsx +15 -33
- package/apps/lib/components/ProfileMenu.tsx +67 -72
- package/apps/lib/components/Radio.tsx +1 -5
- package/apps/lib/components/RadioCard.tsx +9 -28
- package/apps/lib/components/ScrollArea.tsx +45 -43
- package/apps/lib/components/SearchField.tsx +49 -39
- package/apps/lib/components/SearchableSelect.tsx +8 -14
- package/apps/lib/components/SearchableTable.tsx +108 -118
- package/apps/lib/components/SearchableTree.tsx +469 -0
- package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
- package/apps/lib/components/SectionBlock.tsx +4 -16
- package/apps/lib/components/Select.tsx +53 -80
- package/apps/lib/components/SimpleSelect.tsx +196 -187
- package/apps/lib/components/Skeleton.tsx +9 -12
- package/apps/lib/components/SlideDatePicker.tsx +215 -166
- package/apps/lib/components/SpinLoading.tsx +33 -49
- package/apps/lib/components/Stepper.tsx +13 -56
- package/apps/lib/components/Switch.tsx +8 -10
- package/apps/lib/components/TabFormItem.tsx +3 -12
- package/apps/lib/components/TabSwitch.tsx +7 -34
- package/apps/lib/components/Table.tsx +60 -75
- package/apps/lib/components/TableDnDWrapper.ts +15 -48
- package/apps/lib/components/TextEditor.tsx +93 -104
- package/apps/lib/components/Textarea.tsx +8 -12
- package/apps/lib/components/Timeline.tsx +21 -41
- package/apps/lib/components/Toast.tsx +83 -83
- package/apps/lib/components/Toggle.tsx +112 -114
- package/apps/lib/components/ToggleButton.tsx +1 -1
- package/apps/lib/components/Tooltip.tsx +24 -19
- package/apps/lib/components/TransparentLabel.tsx +61 -62
- package/apps/lib/components/TreeDropDown.tsx +86 -52
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
- package/apps/lib/components/TreeFolder/icons.tsx +14 -17
- package/apps/lib/components/TreeFolder/index.ts +15 -8
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
- package/apps/lib/components/TreeFolder/types.ts +32 -32
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
- package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
- package/apps/lib/hooks/useClickOutside.ts +21 -20
- package/apps/lib/hooks/useDataViewsState.ts +86 -80
- package/apps/lib/hooks/useIsMobile.ts +12 -12
- package/apps/lib/hooks/useResize.ts +54 -65
- package/apps/lib/hooks/useTagSelection.ts +201 -201
- package/apps/lib/layouts/CNLayout.tsx +181 -140
- package/apps/lib/layouts/DataViewCard.tsx +4 -18
- package/apps/lib/layouts/FieldSection.tsx +2 -6
- package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
- package/apps/lib/providers/ThemeProvider.tsx +8 -23
- package/apps/lib/registry.json +1004 -0
- package/apps/lib/tsconfig.json +9 -0
- package/apps/lib/utils/cn.ts +1 -1
- package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
- package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
- package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
- package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
- package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
- package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
- package/apps/lib/utils/dateFormat.ts +64 -54
- package/apps/lib/utils/markdownParser.ts +2 -7
- package/apps/lib/utils/resize.ts +21 -25
- package/apps/lib/utils/types.ts +13 -13
- package/dist/bin/index.js +8 -2
- package/dist/bin/index.js.map +1 -1
- package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
- package/dist/src/shared/getAvailableFiles.js +6 -1
- package/dist/src/shared/getAvailableFiles.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +7 -0
- package/dist/src/shared/loadRegistry.d.ts.map +1 -0
- package/dist/src/shared/loadRegistry.js +31 -0
- package/dist/src/shared/loadRegistry.js.map +1 -0
- package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
- package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
- package/dist/src/shared/resolveInstallPlan.js +39 -0
- package/dist/src/shared/resolveInstallPlan.js.map +1 -0
- package/dist/src/types/main.d.ts +24 -0
- package/dist/src/types/main.d.ts.map +1 -1
- package/docs/README.md +10 -2
- package/docs/components/action-button.md +30 -24
- package/docs/components/actions-group.md +26 -20
- package/docs/components/alert-dialog.md +45 -45
- package/docs/components/avatar.md +6 -2
- package/docs/components/badge-field.md +6 -2
- package/docs/components/badge.md +7 -1
- package/docs/components/breadcrumb.md +15 -40
- package/docs/components/button-group.md +13 -10
- package/docs/components/button.md +58 -33
- package/docs/components/calendar.md +26 -19
- package/docs/components/card.md +19 -16
- package/docs/components/chart-block-tool.md +128 -0
- package/docs/components/checkbox.md +16 -8
- package/docs/components/cn-layout.md +7 -1
- package/docs/components/context-menu.md +18 -25
- package/docs/components/count-badge.md +7 -1
- package/docs/components/data-table.md +45 -33
- package/docs/components/data-views-config-panel.md +15 -11
- package/docs/components/data-views-layout.md +13 -16
- package/docs/components/date-picker.md +30 -23
- package/docs/components/dialog.md +43 -42
- package/docs/components/divider.md +10 -4
- package/docs/components/drawer.md +8 -33
- package/docs/components/dropdown-menu.md +25 -34
- package/docs/components/field-hint.md +37 -25
- package/docs/components/field-section.md +9 -3
- package/docs/components/form-stepper.md +6 -0
- package/docs/components/form.md +17 -20
- package/docs/components/header-bar.md +6 -0
- package/docs/components/image-attachment.md +33 -41
- package/docs/components/inbox-view.md +16 -5
- package/docs/components/inner-label-field.md +34 -24
- package/docs/components/input-field.md +18 -10
- package/docs/components/input-otp.md +14 -11
- package/docs/components/input.md +22 -16
- package/docs/components/kanban-view.md +15 -5
- package/docs/components/label-field.md +32 -22
- package/docs/components/label.md +43 -32
- package/docs/components/labeled-check-box.md +16 -8
- package/docs/components/labeled-radio.md +18 -11
- package/docs/components/link-button.md +7 -1
- package/docs/components/login-button.md +8 -2
- package/docs/components/password-level.md +37 -24
- package/docs/components/popover.md +26 -23
- package/docs/components/profile-menu.md +38 -27
- package/docs/components/radio-card.md +16 -9
- package/docs/components/radio.md +16 -8
- package/docs/components/scroll-area.md +6 -2
- package/docs/components/search-field.md +14 -6
- package/docs/components/searchable-select.md +19 -14
- package/docs/components/searchable-table.md +18 -13
- package/docs/components/searchable-tree-dialog.md +190 -0
- package/docs/components/searchable-tree.md +200 -0
- package/docs/components/section-block.md +12 -4
- package/docs/components/select.md +23 -18
- package/docs/components/simple-select.md +14 -10
- package/docs/components/skeleton.md +43 -33
- package/docs/components/slide-date-picker.md +37 -29
- package/docs/components/spin-loading.md +32 -23
- package/docs/components/stepper.md +6 -0
- package/docs/components/switch.md +14 -6
- package/docs/components/tab-form-item.md +7 -1
- package/docs/components/tab-switch.md +13 -6
- package/docs/components/table-dnd-wrapper.md +105 -0
- package/docs/components/table-view.md +15 -5
- package/docs/components/table.md +28 -28
- package/docs/components/text-editor.md +19 -13
- package/docs/components/textarea.md +15 -7
- package/docs/components/timeline.md +6 -0
- package/docs/components/toast.md +35 -26
- package/docs/components/toggle-button.md +24 -21
- package/docs/components/toggle.md +23 -15
- package/docs/components/tooltip.md +42 -30
- package/docs/components/transparent-label.md +29 -20
- package/docs/components/tree-drop-down.md +31 -23
- package/docs/components/tree-sub-layout.md +6 -2
- package/docs/components/tree-view.md +16 -5
- package/docs/explanation/architecture.md +54 -0
- package/docs/explanation/design-system.md +52 -0
- package/docs/how-to/data-views-from-backend-response.md +6 -4
- package/docs/how-to/guides.md +24 -18
- package/docs/migration/changelog.md +38 -0
- package/docs/reference/cli.md +87 -0
- package/docs/reference/components.md +11 -12
- package/docs/reference/hooks.md +8 -8
- package/docs/reference/providers.md +22 -22
- package/docs/reference/tailwind-plugins.md +2 -2
- package/docs/reference/theme.md +85 -0
- package/docs/reference/types.md +4 -4
- package/docs/reference/utilities.md +19 -26
- package/docs/tutorials/building-first-form.md +20 -13
- package/docs/tutorials/component-composition.md +34 -50
- package/docs/tutorials/getting-started.md +2 -2
- package/docs/tutorials/theming-basics.md +13 -10
- package/package.json +31 -3
- package/dist/src/commands/block.d.ts +0 -5
- package/dist/src/commands/block.d.ts.map +0 -1
- package/dist/src/commands/block.js +0 -255
- package/dist/src/commands/block.js.map +0 -1
- package/dist/src/shared/configureFonts.d.ts +0 -6
- package/dist/src/shared/configureFonts.d.ts.map +0 -1
- package/dist/src/shared/configureFonts.js +0 -106
- package/dist/src/shared/configureFonts.js.map +0 -1
- package/dist/src/shared/configureGlobalCss.d.ts +0 -6
- package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
- package/dist/src/shared/configureGlobalCss.js +0 -154
- package/dist/src/shared/configureGlobalCss.js.map +0 -1
- package/dist/src/shared/configureTailwind.d.ts +0 -7
- package/dist/src/shared/configureTailwind.d.ts.map +0 -1
- package/dist/src/shared/configureTailwind.js +0 -163
- package/dist/src/shared/configureTailwind.js.map +0 -1
- package/dist/src/shared/detectFramework.d.ts +0 -23
- package/dist/src/shared/detectFramework.d.ts.map +0 -1
- package/dist/src/shared/detectFramework.js +0 -119
- package/dist/src/shared/detectFramework.js.map +0 -1
- package/dist/src/shared/installBaseUtils.d.ts +0 -5
- package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
- package/dist/src/shared/installBaseUtils.js +0 -79
- package/dist/src/shared/installBaseUtils.js.map +0 -1
- package/dist/src/shared/resolveAliases.d.ts +0 -24
- package/dist/src/shared/resolveAliases.d.ts.map +0 -1
- package/dist/src/shared/resolveAliases.js +0 -98
- package/dist/src/shared/resolveAliases.js.map +0 -1
package/docs/how-to/guides.md
CHANGED
|
@@ -80,8 +80,8 @@ export default {
|
|
|
80
80
|
|
|
81
81
|
```tsx
|
|
82
82
|
// components/BrandButton.tsx
|
|
83
|
-
import { Button } from
|
|
84
|
-
import { cn } from
|
|
83
|
+
import { Button } from "@/components/Button";
|
|
84
|
+
import { cn } from "@/utils/cn";
|
|
85
85
|
|
|
86
86
|
export function BrandButton({ children, ...props }: any) {
|
|
87
87
|
return (
|
|
@@ -103,7 +103,7 @@ export function BrandButton({ children, ...props }: any) {
|
|
|
103
103
|
|
|
104
104
|
```tsx
|
|
105
105
|
// hooks/useCustomTheme.ts
|
|
106
|
-
import { useTheme } from
|
|
106
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
107
107
|
import { useEffect } from 'react';
|
|
108
108
|
|
|
109
109
|
export function useCustomTheme() {
|
|
@@ -130,7 +130,7 @@ export function useCustomTheme() {
|
|
|
130
130
|
|
|
131
131
|
```tsx
|
|
132
132
|
// providers/BrandThemeProvider.tsx
|
|
133
|
-
import { ThemeProvider } from
|
|
133
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
134
134
|
|
|
135
135
|
export function BrandThemeProvider({ children }: { children: React.ReactNode }) {
|
|
136
136
|
return (
|
|
@@ -148,7 +148,7 @@ export function BrandThemeProvider({ children }: { children: React.ReactNode })
|
|
|
148
148
|
```tsx
|
|
149
149
|
// __tests__/BrandButton.test.tsx
|
|
150
150
|
import { render } from '@testing-library/react';
|
|
151
|
-
import { ThemeProvider } from
|
|
151
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
152
152
|
import { BrandButton } from '../components/BrandButton';
|
|
153
153
|
|
|
154
154
|
describe('BrandButton', () => {
|
|
@@ -331,7 +331,9 @@ export const matchField = (otherField: string, message?: string) => {
|
|
|
331
331
|
|
|
332
332
|
import { useFormValidation } from '../hooks/useFormValidation';
|
|
333
333
|
import { required, email, minLength } from '../utils/validationRules';
|
|
334
|
-
import {
|
|
334
|
+
import { Button } from "@/components/Button";
|
|
335
|
+
import { LabelField } from "@/components/LabelField";
|
|
336
|
+
import { toast } from "@/components/Toast";
|
|
335
337
|
|
|
336
338
|
export default function RegistrationForm() {
|
|
337
339
|
const {
|
|
@@ -455,7 +457,8 @@ Implement comprehensive dark mode support.
|
|
|
455
457
|
// components/DarkModeToggle.tsx
|
|
456
458
|
'use client';
|
|
457
459
|
|
|
458
|
-
import {
|
|
460
|
+
import { Button } from "@/components/Button";
|
|
461
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
459
462
|
import { useEffect, useState } from 'react';
|
|
460
463
|
|
|
461
464
|
export default function DarkModeToggle() {
|
|
@@ -469,7 +472,7 @@ export default function DarkModeToggle() {
|
|
|
469
472
|
|
|
470
473
|
if (!mounted) {
|
|
471
474
|
return (
|
|
472
|
-
<Button theme="light" variant="
|
|
475
|
+
<Button theme="light" variant="PrimeContStyle" buttonType="icon">
|
|
473
476
|
<div className="w-5 h-5" />
|
|
474
477
|
</Button>
|
|
475
478
|
);
|
|
@@ -478,7 +481,7 @@ export default function DarkModeToggle() {
|
|
|
478
481
|
return (
|
|
479
482
|
<Button
|
|
480
483
|
theme={theme as any}
|
|
481
|
-
variant="
|
|
484
|
+
variant="PrimeContStyle"
|
|
482
485
|
buttonType="icon"
|
|
483
486
|
onClick={() => updateTheme(theme === 'light' ? 'dark' : 'light')}
|
|
484
487
|
aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} mode`}
|
|
@@ -506,7 +509,7 @@ export default function DarkModeToggle() {
|
|
|
506
509
|
```tsx
|
|
507
510
|
// hooks/useSystemTheme.ts
|
|
508
511
|
import { useEffect } from 'react';
|
|
509
|
-
import { useTheme } from
|
|
512
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
510
513
|
|
|
511
514
|
export function useSystemTheme() {
|
|
512
515
|
const { theme, updateTheme } = useTheme();
|
|
@@ -536,7 +539,7 @@ export function useSystemTheme() {
|
|
|
536
539
|
|
|
537
540
|
```tsx
|
|
538
541
|
// components/ThemedImage.tsx
|
|
539
|
-
import { useTheme } from
|
|
542
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
540
543
|
import Image from 'next/image';
|
|
541
544
|
|
|
542
545
|
interface ThemedImageProps {
|
|
@@ -573,7 +576,7 @@ export function ThemedImage({
|
|
|
573
576
|
```tsx
|
|
574
577
|
// __tests__/DarkMode.test.tsx
|
|
575
578
|
import { render } from '@testing-library/react';
|
|
576
|
-
import { ThemeProvider } from
|
|
579
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
577
580
|
import userEvent from '@testing-library/user-event';
|
|
578
581
|
import DarkModeToggle from '../components/DarkModeToggle';
|
|
579
582
|
|
|
@@ -616,7 +619,7 @@ Ensure your application is accessible to all users.
|
|
|
616
619
|
'use client';
|
|
617
620
|
|
|
618
621
|
import { useState, useRef, useEffect } from 'react';
|
|
619
|
-
import { Button } from
|
|
622
|
+
import { Button } from "@/components/Button";
|
|
620
623
|
|
|
621
624
|
export default function AccessibleMenu() {
|
|
622
625
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -712,7 +715,8 @@ export default function AccessibleMenu() {
|
|
|
712
715
|
|
|
713
716
|
```tsx
|
|
714
717
|
// components/AccessibleForm.tsx
|
|
715
|
-
import {
|
|
718
|
+
import { Button } from "@/components/Button";
|
|
719
|
+
import { LabelField } from "@/components/LabelField";
|
|
716
720
|
import { useState } from 'react';
|
|
717
721
|
|
|
718
722
|
export default function AccessibleForm() {
|
|
@@ -808,7 +812,7 @@ export function useFocusTrap<T extends HTMLElement>(isActive: boolean) {
|
|
|
808
812
|
|
|
809
813
|
```tsx
|
|
810
814
|
// components/AccessibleButton.tsx
|
|
811
|
-
import { Button } from
|
|
815
|
+
import { Button } from "@/components/Button";
|
|
812
816
|
|
|
813
817
|
interface AccessibleButtonProps {
|
|
814
818
|
onClick: () => void;
|
|
@@ -866,7 +870,9 @@ export type FormTouched<T> = Partial<Record<keyof T, boolean>>;
|
|
|
866
870
|
```tsx
|
|
867
871
|
// components/TypeSafeForm.tsx
|
|
868
872
|
import { useState } from 'react';
|
|
869
|
-
import {
|
|
873
|
+
import { Button } from "@/components/Button";
|
|
874
|
+
import { LabelField } from "@/components/LabelField";
|
|
875
|
+
import { toast } from "@/components/Toast";
|
|
870
876
|
import type { ContactForm, FormErrors, FormTouched } from '../types/forms';
|
|
871
877
|
|
|
872
878
|
export default function TypeSafeForm() {
|
|
@@ -981,7 +987,7 @@ export function useTypedLocalStorage<T>(
|
|
|
981
987
|
|
|
982
988
|
```tsx
|
|
983
989
|
// types/components.ts
|
|
984
|
-
import type { ButtonProps } from
|
|
990
|
+
import type { ButtonProps } from "@/components/LoginButton";
|
|
985
991
|
|
|
986
992
|
export interface ExtendedButtonProps extends ButtonProps {
|
|
987
993
|
isLoading?: boolean;
|
|
@@ -991,7 +997,7 @@ export interface ExtendedButtonProps extends ButtonProps {
|
|
|
991
997
|
|
|
992
998
|
```tsx
|
|
993
999
|
// components/ExtendedButton.tsx
|
|
994
|
-
import { Button } from
|
|
1000
|
+
import { Button } from "@/components/Button";
|
|
995
1001
|
import type { ExtendedButtonProps } from '../types/components';
|
|
996
1002
|
|
|
997
1003
|
export function ExtendedButton({
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Changelog & Upgrading
|
|
3
|
+
description: How to upgrade copied TORCH Glare components and where to find release notes.
|
|
4
|
+
group: migration
|
|
5
|
+
keywords: [changelog, migration, upgrade, update]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Changelog & Upgrading
|
|
9
|
+
|
|
10
|
+
## Upgrading in a copy-in library
|
|
11
|
+
|
|
12
|
+
Because components are **copied into your project**, upgrading is not an `npm update`. To pull
|
|
13
|
+
the latest component source, re-run the CLI:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Re-sync everything already installed with the latest templates
|
|
17
|
+
npx torch-glare@latest update
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`update` overwrites your local copies, so review the diff and re-apply any local changes you
|
|
21
|
+
made. To upgrade a single component, re-add it:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx torch-glare@latest add Button
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Release notes
|
|
28
|
+
|
|
29
|
+
- **v1.1.16** — see [CHANGELOG-1.1.16.md](../CHANGELOG-1.1.16.md) (adds `TextEditor`,
|
|
30
|
+
`ChartBlockTool`, and related components).
|
|
31
|
+
|
|
32
|
+
For the authoritative version, check the `version` field in the package's `package.json` or
|
|
33
|
+
run `npx torch-glare --version`.
|
|
34
|
+
|
|
35
|
+
## See also
|
|
36
|
+
|
|
37
|
+
- [CLI reference](../reference/cli.md)
|
|
38
|
+
- [Architecture](../explanation/architecture.md)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CLI Reference
|
|
3
|
+
description: The torch-glare CLI — copy components, hooks, utils, layouts, and providers into your project.
|
|
4
|
+
group: reference
|
|
5
|
+
keywords: [cli, torch-glare, init, add, copy-in, glare.json]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# CLI Reference
|
|
9
|
+
|
|
10
|
+
TORCH Glare is a **copy-in** component library: the `torch-glare` CLI copies source files
|
|
11
|
+
directly into your project (like shadcn/ui). You own the copied code and import it from your
|
|
12
|
+
own local path — you never import components from the npm package.
|
|
13
|
+
|
|
14
|
+
Run any command with `npx` (no global install required):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx torch-glare@latest <command> [name]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Run a command **without** a name to pick from an interactive list.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
| Command | Description |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `init` | Create `glare.json` and set up Tailwind. Run once per project. |
|
|
27
|
+
| `add [Component]` | Copy a component **and its dependencies** into your project. |
|
|
28
|
+
| `hook [hook]` | Copy a hook (usually pulled in automatically as a dependency). |
|
|
29
|
+
| `util [util]` | Copy a utility (e.g. `cn`, usually pulled in automatically). |
|
|
30
|
+
| `layout [layout]` | Copy a layout. |
|
|
31
|
+
| `provider [provider]` | Copy a provider (e.g. `ThemeProvider`). |
|
|
32
|
+
| `update` | Re-sync everything already installed with the latest templates. |
|
|
33
|
+
|
|
34
|
+
Component names are **case-sensitive PascalCase** — `add DatePicker`, not `add datepicker`.
|
|
35
|
+
|
|
36
|
+
## `init`
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx torch-glare@latest init
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Creates `glare.json` and configures Tailwind. `glare.json` controls where files are copied:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"path": "@/"
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Files are copied into `<path>/components`, `<path>/hooks`, `<path>/utils`,
|
|
51
|
+
`<path>/layouts`, and `<path>/providers`. Import them from that path.
|
|
52
|
+
|
|
53
|
+
## `add`
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx torch-glare@latest add Button
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Copies `Button` **plus its full dependency closure** — nested components, hooks, and utils —
|
|
60
|
+
and installs any required npm packages (e.g. `@radix-ui/*`) using your project's package
|
|
61
|
+
manager. After adding, import from your local alias:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { Button } from "@/components/Button";
|
|
65
|
+
|
|
66
|
+
export function Example() {
|
|
67
|
+
return <Button variant="PrimeStyle">Click me</Button>;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Existing files are never overwritten; use `update` to re-sync.
|
|
72
|
+
|
|
73
|
+
## `update`
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx torch-glare@latest update
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Re-copies every installed component, hook, util, layout, and provider from the latest
|
|
80
|
+
templates. Review the diff afterward, since it overwrites your local copies.
|
|
81
|
+
|
|
82
|
+
## See also
|
|
83
|
+
|
|
84
|
+
- [Theme reference](./theme.md)
|
|
85
|
+
- [Components reference](./components.md)
|
|
86
|
+
- [Hooks reference](./hooks.md)
|
|
87
|
+
- [Providers reference](./providers.md)
|
|
@@ -30,7 +30,7 @@ Interactive button component with multiple variants and sizes.
|
|
|
30
30
|
|
|
31
31
|
- **File**: [button.md](../components/button.md)
|
|
32
32
|
- **Props**: `variant`, `size`, `theme`, `buttonType`, `disabled`
|
|
33
|
-
- **Variants**: `PrimeStyle`, `
|
|
33
|
+
- **Variants**: `PrimeStyle`, `BluSecStyle`, `YelSecStyle`, `RedSecStyle`, `BorderStyle`, `PrimeContStyle`, `BluContStyle`, `RedContStyle`
|
|
34
34
|
- **Use Cases**: Primary actions, secondary actions, icon buttons, loading states
|
|
35
35
|
|
|
36
36
|
### Input
|
|
@@ -521,12 +521,13 @@ Components with size variants typically support:
|
|
|
521
521
|
|
|
522
522
|
Button variants:
|
|
523
523
|
- `PrimeStyle` - Primary action
|
|
524
|
-
- `
|
|
525
|
-
- `
|
|
524
|
+
- `BluSecStyle` - Blue secondary action
|
|
525
|
+
- `YelSecStyle` - Yellow secondary action
|
|
526
|
+
- `RedSecStyle` - Red secondary action
|
|
526
527
|
- `BorderStyle` - Outlined
|
|
527
|
-
- `
|
|
528
|
-
- `
|
|
529
|
-
- `
|
|
528
|
+
- `PrimeContStyle` - Primary container (transparent)
|
|
529
|
+
- `BluContStyle` - Blue container (transparent)
|
|
530
|
+
- `RedContStyle` - Red container (transparent)
|
|
530
531
|
|
|
531
532
|
---
|
|
532
533
|
|
|
@@ -535,12 +536,10 @@ Button variants:
|
|
|
535
536
|
All components are fully typed with TypeScript. Import types from the library:
|
|
536
537
|
|
|
537
538
|
```typescript
|
|
538
|
-
import type {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
// ... other types
|
|
543
|
-
} from '@torch-ai/torch-glare';
|
|
539
|
+
import type { ButtonProps } from "@/components/Button";
|
|
540
|
+
import type { InputProps } from "@/components/InputProps";
|
|
541
|
+
import type { ButtonProps } from "@/components/LoginButton";
|
|
542
|
+
import type { SelectProps } from "@/components/SelectProps";
|
|
544
543
|
```
|
|
545
544
|
|
|
546
545
|
---
|
package/docs/reference/hooks.md
CHANGED
|
@@ -30,7 +30,7 @@ Tracks which tree item is most visible in the viewport using the IntersectionObs
|
|
|
30
30
|
### Basic Usage
|
|
31
31
|
|
|
32
32
|
```tsx
|
|
33
|
-
import { useActiveTreeItem } from
|
|
33
|
+
import { useActiveTreeItem } from "@/hooks/useActiveTreeItem";
|
|
34
34
|
|
|
35
35
|
function TableOfContents() {
|
|
36
36
|
const sectionIds = ['intro', 'features', 'api', 'examples'];
|
|
@@ -210,7 +210,7 @@ Detects clicks outside a referenced element and executes a callback. Perfect for
|
|
|
210
210
|
### Basic Usage
|
|
211
211
|
|
|
212
212
|
```tsx
|
|
213
|
-
import { useClickOutside } from
|
|
213
|
+
import { useClickOutside } from "@/hooks/useClickOutside";
|
|
214
214
|
import { useState } from 'react';
|
|
215
215
|
|
|
216
216
|
function Dropdown() {
|
|
@@ -383,7 +383,7 @@ Handles element resizing with support for both mouse and touch events, including
|
|
|
383
383
|
### Basic Usage
|
|
384
384
|
|
|
385
385
|
```tsx
|
|
386
|
-
import { useResize } from
|
|
386
|
+
import { useResize } from "@/hooks/useResize";
|
|
387
387
|
import { useRef } from 'react';
|
|
388
388
|
|
|
389
389
|
function ResizablePanel() {
|
|
@@ -630,7 +630,7 @@ Manages tag selection state with comprehensive keyboard navigation support. Supp
|
|
|
630
630
|
### Basic Multi-Select
|
|
631
631
|
|
|
632
632
|
```tsx
|
|
633
|
-
import { useTagSelection } from
|
|
633
|
+
import { useTagSelection } from "@/hooks/useTagSelection";
|
|
634
634
|
import { useRef } from 'react';
|
|
635
635
|
|
|
636
636
|
function TagSelector() {
|
|
@@ -1177,7 +1177,7 @@ const result = useTagSelection({
|
|
|
1177
1177
|
|
|
1178
1178
|
```tsx
|
|
1179
1179
|
import { renderHook } from '@testing-library/react';
|
|
1180
|
-
import { useActiveTreeItem } from
|
|
1180
|
+
import { useActiveTreeItem } from "@/hooks/useActiveTreeItem";
|
|
1181
1181
|
|
|
1182
1182
|
describe('useActiveTreeItem', () => {
|
|
1183
1183
|
it('should track active item', () => {
|
|
@@ -1208,7 +1208,7 @@ describe('useActiveTreeItem', () => {
|
|
|
1208
1208
|
|
|
1209
1209
|
```tsx
|
|
1210
1210
|
import { render, fireEvent } from '@testing-library/react';
|
|
1211
|
-
import { useClickOutside } from
|
|
1211
|
+
import { useClickOutside } from "@/hooks/useClickOutside";
|
|
1212
1212
|
|
|
1213
1213
|
describe('useClickOutside', () => {
|
|
1214
1214
|
it('should call callback on outside click', () => {
|
|
@@ -1245,7 +1245,7 @@ describe('useClickOutside', () => {
|
|
|
1245
1245
|
|
|
1246
1246
|
```tsx
|
|
1247
1247
|
import { renderHook, act } from '@testing-library/react';
|
|
1248
|
-
import { useResize } from
|
|
1248
|
+
import { useResize } from "@/hooks/useResize";
|
|
1249
1249
|
|
|
1250
1250
|
describe('useResize', () => {
|
|
1251
1251
|
it('should handle resize', () => {
|
|
@@ -1279,7 +1279,7 @@ describe('useResize', () => {
|
|
|
1279
1279
|
|
|
1280
1280
|
```tsx
|
|
1281
1281
|
import { renderHook, act } from '@testing-library/react';
|
|
1282
|
-
import { useTagSelection } from
|
|
1282
|
+
import { useTagSelection } from "@/hooks/useTagSelection";
|
|
1283
1283
|
|
|
1284
1284
|
describe('useTagSelection', () => {
|
|
1285
1285
|
const mockTags = [
|
|
@@ -34,7 +34,7 @@ Manages application theme state with support for light, dark, and system default
|
|
|
34
34
|
### Basic Setup
|
|
35
35
|
|
|
36
36
|
```tsx
|
|
37
|
-
import { ThemeProvider } from
|
|
37
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
38
38
|
|
|
39
39
|
function App() {
|
|
40
40
|
return (
|
|
@@ -48,7 +48,7 @@ function App() {
|
|
|
48
48
|
### With Default Theme
|
|
49
49
|
|
|
50
50
|
```tsx
|
|
51
|
-
import { ThemeProvider } from
|
|
51
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
52
52
|
|
|
53
53
|
function App() {
|
|
54
54
|
return (
|
|
@@ -62,7 +62,7 @@ function App() {
|
|
|
62
62
|
### Consuming Theme with useTheme Hook
|
|
63
63
|
|
|
64
64
|
```tsx
|
|
65
|
-
import { useTheme } from
|
|
65
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
66
66
|
|
|
67
67
|
function ThemeToggle() {
|
|
68
68
|
const { theme, updateTheme } = useTheme();
|
|
@@ -83,7 +83,7 @@ function ThemeToggle() {
|
|
|
83
83
|
### Theme Mode Switcher
|
|
84
84
|
|
|
85
85
|
```tsx
|
|
86
|
-
import { useTheme } from
|
|
86
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
87
87
|
|
|
88
88
|
function ThemeModeSwitcher() {
|
|
89
89
|
const { themeMode, updateMode } = useTheme();
|
|
@@ -105,7 +105,7 @@ function ThemeModeSwitcher() {
|
|
|
105
105
|
### Complete Theme Control Panel
|
|
106
106
|
|
|
107
107
|
```tsx
|
|
108
|
-
import { useTheme } from
|
|
108
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
109
109
|
|
|
110
110
|
function ThemeControlPanel() {
|
|
111
111
|
const { theme, themeMode, updateTheme, updateMode } = useTheme();
|
|
@@ -166,7 +166,7 @@ function ThemeControlPanel() {
|
|
|
166
166
|
### Theme-Aware Component
|
|
167
167
|
|
|
168
168
|
```tsx
|
|
169
|
-
import { useTheme } from
|
|
169
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
170
170
|
|
|
171
171
|
function ThemedCard({ children }: { children: React.ReactNode }) {
|
|
172
172
|
const { theme } = useTheme();
|
|
@@ -188,7 +188,7 @@ function ThemedCard({ children }: { children: React.ReactNode }) {
|
|
|
188
188
|
### System Theme Detection
|
|
189
189
|
|
|
190
190
|
```tsx
|
|
191
|
-
import { useTheme } from
|
|
191
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
192
192
|
import { useEffect, useState } from 'react';
|
|
193
193
|
|
|
194
194
|
function SystemThemeSync() {
|
|
@@ -229,7 +229,7 @@ function SystemThemeSync() {
|
|
|
229
229
|
### Header with Theme Toggle
|
|
230
230
|
|
|
231
231
|
```tsx
|
|
232
|
-
import { useTheme } from
|
|
232
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
233
233
|
|
|
234
234
|
function Header() {
|
|
235
235
|
const { theme, updateTheme } = useTheme();
|
|
@@ -253,7 +253,7 @@ function Header() {
|
|
|
253
253
|
### Settings Page
|
|
254
254
|
|
|
255
255
|
```tsx
|
|
256
|
-
import { useTheme } from
|
|
256
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
257
257
|
import { useState } from 'react';
|
|
258
258
|
|
|
259
259
|
function SettingsPage() {
|
|
@@ -310,7 +310,7 @@ function SettingsPage() {
|
|
|
310
310
|
|
|
311
311
|
```tsx
|
|
312
312
|
// app/layout.tsx
|
|
313
|
-
import { ThemeProvider } from
|
|
313
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
314
314
|
|
|
315
315
|
export default function RootLayout({
|
|
316
316
|
children,
|
|
@@ -333,7 +333,7 @@ export default function RootLayout({
|
|
|
333
333
|
|
|
334
334
|
```tsx
|
|
335
335
|
// pages/_app.tsx
|
|
336
|
-
import { ThemeProvider } from
|
|
336
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
337
337
|
import type { AppProps } from 'next/app';
|
|
338
338
|
|
|
339
339
|
export default function App({ Component, pageProps }: AppProps) {
|
|
@@ -351,7 +351,7 @@ export default function App({ Component, pageProps }: AppProps) {
|
|
|
351
351
|
// main.tsx
|
|
352
352
|
import React from 'react';
|
|
353
353
|
import ReactDOM from 'react-dom/client';
|
|
354
|
-
import { ThemeProvider } from
|
|
354
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
355
355
|
import App from './App';
|
|
356
356
|
|
|
357
357
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
@@ -478,7 +478,7 @@ The ThemeProvider stores values in localStorage:
|
|
|
478
478
|
Full TypeScript support with type inference:
|
|
479
479
|
|
|
480
480
|
```typescript
|
|
481
|
-
import { useTheme } from
|
|
481
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
482
482
|
|
|
483
483
|
function MyComponent() {
|
|
484
484
|
const { theme, themeMode, updateTheme, updateMode } = useTheme();
|
|
@@ -506,7 +506,7 @@ function MyComponent() {
|
|
|
506
506
|
|
|
507
507
|
```tsx
|
|
508
508
|
import { render } from '@testing-library/react';
|
|
509
|
-
import { ThemeProvider } from
|
|
509
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
510
510
|
|
|
511
511
|
describe('ThemedComponent', () => {
|
|
512
512
|
it('should render with light theme', () => {
|
|
@@ -535,7 +535,7 @@ describe('ThemedComponent', () => {
|
|
|
535
535
|
|
|
536
536
|
```tsx
|
|
537
537
|
import { renderHook, act } from '@testing-library/react';
|
|
538
|
-
import { ThemeProvider, useTheme } from
|
|
538
|
+
import { ThemeProvider, useTheme } from "@/providers/ThemeProvider";
|
|
539
539
|
|
|
540
540
|
describe('useTheme', () => {
|
|
541
541
|
it('should update theme', () => {
|
|
@@ -630,7 +630,7 @@ The ThemeProvider uses React context, which can cause re-renders. To optimize:
|
|
|
630
630
|
|
|
631
631
|
```tsx
|
|
632
632
|
import { memo } from 'react';
|
|
633
|
-
import { useTheme } from
|
|
633
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
634
634
|
|
|
635
635
|
// Memoize components that don't need theme updates
|
|
636
636
|
const ExpensiveComponent = memo(() => {
|
|
@@ -647,7 +647,7 @@ function ThemedButton() {
|
|
|
647
647
|
### Selective Theme Consumption
|
|
648
648
|
|
|
649
649
|
```tsx
|
|
650
|
-
import { useTheme } from
|
|
650
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
651
651
|
|
|
652
652
|
// Only consume what you need
|
|
653
653
|
function ThemeToggle() {
|
|
@@ -727,7 +727,7 @@ Avoid hydration mismatches:
|
|
|
727
727
|
|
|
728
728
|
```tsx
|
|
729
729
|
import { useEffect, useState } from 'react';
|
|
730
|
-
import { useTheme } from
|
|
730
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
731
731
|
|
|
732
732
|
function ClientOnlyThemeButton() {
|
|
733
733
|
const [mounted, setMounted] = useState(false);
|
|
@@ -754,7 +754,7 @@ function ClientOnlyThemeButton() {
|
|
|
754
754
|
Show visual feedback when theme changes:
|
|
755
755
|
|
|
756
756
|
```tsx
|
|
757
|
-
import { useTheme } from
|
|
757
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
758
758
|
import { useState, useEffect } from 'react';
|
|
759
759
|
|
|
760
760
|
function ThemeToggleWithFeedback() {
|
|
@@ -783,7 +783,7 @@ function ThemeToggleWithFeedback() {
|
|
|
783
783
|
Ensure theme values are valid before updating:
|
|
784
784
|
|
|
785
785
|
```tsx
|
|
786
|
-
import { useTheme } from
|
|
786
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
787
787
|
|
|
788
788
|
function SafeThemeUpdater({ theme }: { theme: string }) {
|
|
789
789
|
const { updateTheme } = useTheme();
|
|
@@ -849,7 +849,7 @@ import { Theme } from 'old-library';
|
|
|
849
849
|
<Theme mode="dark">
|
|
850
850
|
|
|
851
851
|
// v2.x (new)
|
|
852
|
-
import { ThemeProvider } from
|
|
852
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
853
853
|
<ThemeProvider defaultTheme="dark">
|
|
854
854
|
```
|
|
855
855
|
|
|
@@ -860,7 +860,7 @@ import { ThemeProvider } from '@torch-ai/torch-glare';
|
|
|
860
860
|
import { ThemeProvider as NextThemeProvider } from 'next-themes';
|
|
861
861
|
|
|
862
862
|
// TORCH Glare
|
|
863
|
-
import { ThemeProvider } from
|
|
863
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
864
864
|
|
|
865
865
|
// Both can coexist if needed, but use TORCH Glare for consistency
|
|
866
866
|
```
|
|
@@ -352,7 +352,7 @@ The TORCH mode plugin defines the actual color values for:
|
|
|
352
352
|
### Integration with ThemeProvider
|
|
353
353
|
|
|
354
354
|
```tsx
|
|
355
|
-
import { ThemeProvider } from
|
|
355
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
356
356
|
|
|
357
357
|
function App() {
|
|
358
358
|
return (
|
|
@@ -622,7 +622,7 @@ export default {
|
|
|
622
622
|
|
|
623
623
|
```tsx
|
|
624
624
|
// app/layout.tsx (Next.js App Router)
|
|
625
|
-
import { ThemeProvider } from
|
|
625
|
+
import { ThemeProvider } from "@/providers/ThemeProvider";
|
|
626
626
|
import './globals.css';
|
|
627
627
|
|
|
628
628
|
export default function RootLayout({
|