@umituz/web-dashboard 4.6.5 → 4.7.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.
Files changed (29) hide show
  1. package/package.json +3 -10
  2. package/src/{domain/config → config}/DashboardConfig.ts +1 -1
  3. package/src/config/index.ts +1 -0
  4. package/src/{domain/config/CalendarConfig.ts → domains/calendar/config.ts} +1 -1
  5. package/src/domains/calendar/hooks/useCalendar.ts +1 -1
  6. package/src/domains/calendar/index.ts +1 -0
  7. package/src/domains/calendar/utils/index.ts +0 -6
  8. package/src/domains/layouts/components/DashboardHeader.tsx +21 -13
  9. package/src/domains/layouts/types/index.ts +1 -1
  10. package/src/domains/layouts/types/layout.ts +18 -0
  11. package/src/index.ts +2 -14
  12. package/src/styles/dashboard.css +1 -652
  13. package/src/domain/config/index.ts +0 -6
  14. package/src/domains/onboarding/components/AppFocusStep.tsx +0 -144
  15. package/src/domains/onboarding/components/OnboardingWizard.tsx +0 -188
  16. package/src/domains/onboarding/components/PlanStep.tsx +0 -241
  17. package/src/domains/onboarding/components/PlatformsStep.tsx +0 -129
  18. package/src/domains/onboarding/components/StepNavigation.tsx +0 -108
  19. package/src/domains/onboarding/components/StepProgress.tsx +0 -62
  20. package/src/domains/onboarding/components/UserTypeStep.tsx +0 -114
  21. package/src/domains/onboarding/components/index.ts +0 -13
  22. package/src/domains/onboarding/hooks/index.ts +0 -5
  23. package/src/domains/onboarding/hooks/useOnboarding.ts +0 -156
  24. package/src/domains/onboarding/index.ts +0 -36
  25. package/src/domains/onboarding/types/index.ts +0 -16
  26. package/src/domains/onboarding/types/onboarding.ts +0 -254
  27. package/src/domains/onboarding/utils/i18nKeys.ts +0 -72
  28. package/src/domains/onboarding/utils/index.ts +0 -17
  29. package/src/domains/onboarding/utils/onboarding.ts +0 -166
@@ -1,108 +0,0 @@
1
- /**
2
- * Onboarding - Step Navigation Footer
3
- *
4
- * Renders the wizard's bottom action bar: back, skip, next/getStarted.
5
- * All labels are i18n keys; the consumer maps them to localized strings.
6
- */
7
-
8
- import { ArrowLeft, Loader2 } from "lucide-react";
9
- import { Button } from "../../../primitives";
10
-
11
- /**
12
- * Centralized i18n keys for navigation labels.
13
- * Components stay free of hardcoded UI strings.
14
- */
15
- export const STEP_NAVIGATION_KEYS = {
16
- back: 'onboarding.buttons.back',
17
- skip: 'onboarding.buttons.skip',
18
- next: 'onboarding.buttons.next',
19
- getStarted: 'onboarding.buttons.getStarted',
20
- finalizing: 'onboarding.buttons.finalizing',
21
- } as const;
22
-
23
- export type StepNavigationKey =
24
- (typeof STEP_NAVIGATION_KEYS)[keyof typeof STEP_NAVIGATION_KEYS];
25
-
26
- /**
27
- * Translation function shape consumers must inject.
28
- * The wizard never depends on a specific i18n library.
29
- */
30
- export type Translate = (key: string) => string;
31
-
32
- export interface StepNavigationProps {
33
- currentStep: number;
34
- totalSteps: number;
35
- canGoNext: boolean;
36
- isSaving?: boolean;
37
- nextLabel?: string;
38
- prevLabel?: string;
39
- onNext: () => void;
40
- onPrev: () => void;
41
- allowSkip?: boolean;
42
- onSkip?: () => void;
43
- translate: Translate;
44
- }
45
-
46
- export const StepNavigation = ({
47
- currentStep,
48
- totalSteps,
49
- canGoNext,
50
- isSaving = false,
51
- nextLabel,
52
- prevLabel,
53
- onNext,
54
- onPrev,
55
- allowSkip = false,
56
- onSkip,
57
- translate: t,
58
- }: StepNavigationProps) => {
59
- const isLastStep = currentStep === totalSteps;
60
-
61
- return (
62
- <footer className="udb-onboarding__footer">
63
- {currentStep > 1 ? (
64
- <Button
65
- variant="ghost"
66
- onClick={onPrev}
67
- className="udb-onboarding__footer-btn"
68
- disabled={isSaving}
69
- >
70
- <ArrowLeft className="udb-onboarding__footer-icon" aria-hidden="true" />
71
- {prevLabel ?? t(STEP_NAVIGATION_KEYS.back)}
72
- </Button>
73
- ) : (
74
- <div />
75
- )}
76
-
77
- <div className="udb-onboarding__footer-actions">
78
- {allowSkip && onSkip && !isLastStep && (
79
- <Button
80
- variant="ghost"
81
- onClick={onSkip}
82
- className="udb-onboarding__footer-btn"
83
- disabled={isSaving}
84
- >
85
- {t(STEP_NAVIGATION_KEYS.skip)}
86
- </Button>
87
- )}
88
-
89
- <Button
90
- onClick={onNext}
91
- className="udb-onboarding__footer-next"
92
- disabled={!canGoNext || isSaving}
93
- >
94
- {isSaving ? (
95
- <>
96
- <Loader2 className="udb-onboarding__footer-icon udb-spin" aria-hidden="true" />
97
- {t(STEP_NAVIGATION_KEYS.finalizing)}
98
- </>
99
- ) : isLastStep ? (
100
- nextLabel ?? t(STEP_NAVIGATION_KEYS.getStarted)
101
- ) : (
102
- t(STEP_NAVIGATION_KEYS.next)
103
- )}
104
- </Button>
105
- </div>
106
- </footer>
107
- );
108
- };
@@ -1,62 +0,0 @@
1
- /**
2
- * Onboarding - Step Progress Indicator
3
- *
4
- * Renders the wizard's progress as a row of numbered nodes connected
5
- * by lines. Stateless: receives all data via props.
6
- */
7
-
8
- import { Check } from "lucide-react";
9
- import { cn } from "../../../primitives";
10
-
11
- interface StepProgressProps {
12
- currentStep: number;
13
- totalSteps: number;
14
- completedSteps?: number[];
15
- }
16
-
17
- export const StepProgress = ({
18
- currentStep,
19
- totalSteps,
20
- completedSteps = [],
21
- }: StepProgressProps) => {
22
- return (
23
- <div
24
- className="udb-progress"
25
- role="progressbar"
26
- aria-valuemin={1}
27
- aria-valuemax={totalSteps}
28
- aria-valuenow={currentStep}
29
- >
30
- {Array.from({ length: totalSteps }, (_, i) => i + 1).map((step) => {
31
- const isCompleted = completedSteps.includes(step) || step < currentStep;
32
- const isCurrent = step === currentStep;
33
-
34
- return (
35
- <div key={step} className="udb-progress__segment">
36
- <div
37
- className={cn(
38
- "udb-progress__node",
39
- (isCompleted || isCurrent) && "udb-progress__node--on",
40
- )}
41
- aria-current={isCurrent ? "step" : undefined}
42
- >
43
- {isCompleted ? (
44
- <Check className="udb-progress__check" aria-hidden="true" />
45
- ) : (
46
- step
47
- )}
48
- </div>
49
- {step < totalSteps && (
50
- <div
51
- className={cn(
52
- "udb-progress__connector",
53
- step < currentStep && "udb-progress__connector--on",
54
- )}
55
- />
56
- )}
57
- </div>
58
- );
59
- })}
60
- </div>
61
- );
62
- };
@@ -1,114 +0,0 @@
1
- /**
2
- * User Type Step
3
- *
4
- * First step of the onboarding wizard: select user type.
5
- * String props are expected to be already-translated by the consumer
6
- * (so the consumer can localize each option via i18n).
7
- */
8
-
9
- import { Check } from "lucide-react";
10
- import { useT } from "../../../i18n";
11
- import { cn } from "../../../primitives";
12
- import type { OnboardingState, UserTypeOption } from "../types/onboarding";
13
- import type { ComponentType } from "react";
14
- import { ONBOARDING_KEYS } from "../utils/i18nKeys";
15
-
16
- export interface UserTypeStepProps {
17
- /** Current onboarding state */
18
- state: OnboardingState;
19
- /** Update state function */
20
- updateState: (updates: Partial<OnboardingState>) => void;
21
- /** User type options — labels/desc are translated by the consumer */
22
- options?: UserTypeOption[];
23
- /** Custom icon component type (avoids `React.ComponentType` import here) */
24
- iconComponent?: ComponentType<{ className?: string }>;
25
- }
26
-
27
- /**
28
- * Default options — every string is an i18n key. The consumer
29
- * supplies translations; nothing in this file is hardcoded copy.
30
- */
31
- const DEFAULT_OPTIONS: UserTypeOption[] = [
32
- { id: "founder", labelKey: ONBOARDING_KEYS.defaults.founder, descriptionKey: ONBOARDING_KEYS.defaults.founderDescription },
33
- { id: "creator", labelKey: ONBOARDING_KEYS.defaults.contentCreator, descriptionKey: ONBOARDING_KEYS.defaults.contentCreatorDescription },
34
- { id: "agency", labelKey: ONBOARDING_KEYS.defaults.agency, descriptionKey: ONBOARDING_KEYS.defaults.agencyDescription },
35
- { id: "enterprise", labelKey: ONBOARDING_KEYS.defaults.enterprise, descriptionKey: ONBOARDING_KEYS.defaults.enterpriseDescription },
36
- { id: "small-business", labelKey: ONBOARDING_KEYS.defaults.smallBusiness, descriptionKey: ONBOARDING_KEYS.defaults.smallBusinessDescription },
37
- { id: "personal", labelKey: ONBOARDING_KEYS.defaults.personal, descriptionKey: ONBOARDING_KEYS.defaults.personalDescription },
38
- ];
39
-
40
- export const UserTypeStep = ({
41
- state,
42
- updateState,
43
- options = [],
44
- }: UserTypeStepProps) => {
45
- const t = useT();
46
- const userTypeOptions = options.length > 0 ? options : DEFAULT_OPTIONS;
47
-
48
- return (
49
- <div className="udb-step">
50
- <div className="udb-step__header">
51
- <h1 className="udb-step__title">
52
- {t(ONBOARDING_KEYS.userType.title)}
53
- </h1>
54
- <p className="udb-step__description">
55
- {t(ONBOARDING_KEYS.userType.description)}
56
- </p>
57
- </div>
58
-
59
- <div className="udb-step__options udb-step__options--list" role="radiogroup" aria-label={t(ONBOARDING_KEYS.userType.title)}>
60
- {userTypeOptions.map((option) => {
61
- const isSelected = state.selectedUserType === option.id;
62
- const hasBadge = option.badge != null;
63
- const hasIcon = option.icon != null;
64
- const label = option.label ?? (option.labelKey ? t(option.labelKey) : '');
65
- const description = option.description ?? (option.descriptionKey ? t(option.descriptionKey) : '');
66
-
67
- return (
68
- <button
69
- key={option.id}
70
- type="button"
71
- role="radio"
72
- aria-checked={isSelected}
73
- onClick={() => updateState({ selectedUserType: option.id })}
74
- className={cn(
75
- "udb-choice",
76
- isSelected && "udb-choice--selected",
77
- )}
78
- >
79
- <span
80
- className={cn(
81
- "udb-choice__check",
82
- isSelected && "udb-choice__check--on",
83
- )}
84
- aria-hidden="true"
85
- >
86
- {isSelected && <Check className="udb-choice__check-icon" />}
87
- </span>
88
-
89
- <span className="udb-choice__body">
90
- <span className="udb-choice__label-row">
91
- <span className="udb-choice__label">{label}</span>
92
- {hasBadge && (
93
- <span className="udb-choice__badge">
94
- {option.badge}
95
- </span>
96
- )}
97
- </span>
98
- <span className="udb-choice__description">{description}</span>
99
- </span>
100
-
101
- {hasIcon && option.icon && (
102
- <span className="udb-choice__icon-box">
103
- <option.icon className="udb-choice__icon" aria-hidden="true" />
104
- </span>
105
- )}
106
- </button>
107
- );
108
- })}
109
- </div>
110
- </div>
111
- );
112
- };
113
-
114
- export default UserTypeStep;
@@ -1,13 +0,0 @@
1
- /**
2
- * Onboarding Components Export
3
- */
4
-
5
- export { OnboardingWizard } from './OnboardingWizard';
6
- export { UserTypeStep } from './UserTypeStep';
7
- export { AppFocusStep } from './AppFocusStep';
8
- export { PlatformsStep } from './PlatformsStep';
9
- export { PlanStep } from './PlanStep';
10
- export { StepProgress } from './StepProgress';
11
- export { StepNavigation } from './StepNavigation';
12
- export { STEP_NAVIGATION_KEYS } from './StepNavigation';
13
- export type { StepNavigationKey, Translate } from './StepNavigation';
@@ -1,5 +0,0 @@
1
- /**
2
- * Onboarding Hooks Export
3
- */
4
-
5
- export { useOnboarding, useOnboardingStep } from './useOnboarding';
@@ -1,156 +0,0 @@
1
- /**
2
- * Onboarding Hooks
3
- *
4
- * Custom React hooks for onboarding functionality. Navigation callbacks
5
- * read the current render's state so their boolean return values are
6
- * truthful; state updaters themselves stay pure.
7
- */
8
-
9
- import { useState, useCallback, useMemo, useRef } from "react";
10
- import type { OnboardingState, OnboardingConfig } from "../types/onboarding";
11
-
12
- /**
13
- * Initial onboarding state — single source of truth.
14
- */
15
- const buildInitialState = (
16
- initialState?: Partial<OnboardingState>,
17
- ): OnboardingState => ({
18
- currentStep: 1,
19
- connectedPlatforms: [],
20
- billingCycle: "monthly",
21
- stepData: {},
22
- ...initialState,
23
- });
24
-
25
- /**
26
- * Use Onboarding Hook
27
- *
28
- * Manages onboarding state and actions.
29
- *
30
- * @param config - Onboarding configuration
31
- * @param initialState - Initial state overrides
32
- * @returns Onboarding state and actions
33
- */
34
- export function useOnboarding(
35
- config: OnboardingConfig,
36
- initialState?: Partial<OnboardingState>,
37
- ) {
38
- const [state, setState] = useState<OnboardingState>(() => buildInitialState(initialState));
39
-
40
- const totalSteps = config.steps.length;
41
-
42
- // Validation and the boolean return value are computed against the
43
- // current render's state (always fresh — these callbacks are
44
- // recreated when state changes); the setState updater stays pure and
45
- // bounds-checked. The previous version flipped a closure variable
46
- // inside the updater, which returned false before React had run it.
47
- const goToNext = useCallback((): boolean => {
48
- const currentStepConfig = config.steps[state.currentStep - 1];
49
- if (currentStepConfig?.validate && !currentStepConfig.validate(state)) {
50
- return false;
51
- }
52
- if (state.currentStep >= totalSteps) return false;
53
- setState((prev) =>
54
- prev.currentStep < totalSteps
55
- ? { ...prev, currentStep: prev.currentStep + 1 }
56
- : prev,
57
- );
58
- return true;
59
- }, [config.steps, state, totalSteps]);
60
-
61
- const goToPrev = useCallback((): boolean => {
62
- if (state.currentStep <= 1) return false;
63
- setState((prev) =>
64
- prev.currentStep > 1
65
- ? { ...prev, currentStep: prev.currentStep - 1 }
66
- : prev,
67
- );
68
- return true;
69
- }, [state]);
70
-
71
- const goToStep = useCallback((step: number) => {
72
- setState((prev) => {
73
- if (step >= 1 && step <= totalSteps && step !== prev.currentStep) {
74
- return { ...prev, currentStep: step };
75
- }
76
- return prev;
77
- });
78
- }, [totalSteps]);
79
-
80
- const updateState = useCallback((updates: Partial<OnboardingState>) => {
81
- setState((prev) => ({ ...prev, ...updates }));
82
- }, []);
83
-
84
- // Whether the current step passes its configured validator.
85
- const canGoNext = useCallback((): boolean => {
86
- const currentStepConfig = config.steps[state.currentStep - 1];
87
- return currentStepConfig?.validate ? currentStepConfig.validate(state) : true;
88
- }, [config.steps, state]);
89
-
90
- // The `isFirstStep` / `isLastStep` derivations are cheap, but
91
- // memoizing them avoids re-creating the object on every render.
92
- const derived = useMemo(() => {
93
- const isFirstStep = state.currentStep === 1;
94
- const isLastStep = state.currentStep === totalSteps;
95
- const progress = totalSteps === 0 ? 0 : (state.currentStep / totalSteps) * 100;
96
- return { isFirstStep, isLastStep, progress };
97
- }, [state.currentStep, totalSteps]);
98
-
99
- return {
100
- state,
101
- currentStep: state.currentStep,
102
- totalSteps,
103
- isFirstStep: derived.isFirstStep,
104
- isLastStep: derived.isLastStep,
105
- progress: derived.progress,
106
- goToNext,
107
- goToPrev,
108
- goToStep,
109
- updateState,
110
- canGoNext,
111
- };
112
- }
113
-
114
- /**
115
- * Use Onboarding Step Hook
116
- *
117
- * Hook for managing individual step state.
118
- */
119
- export function useOnboardingStep(stepId: string) {
120
- const [data, setData] = useState<Record<string, unknown>>({});
121
- const [isValid, setIsValid] = useState(false);
122
- const [isTouched, setIsTouched] = useState(false);
123
-
124
- // Latest-ref mirror of `data` so `validate` can read the most recent
125
- // value synchronously. State updaters must stay pure — the previous
126
- // version called setIsValid inside the setData updater.
127
- const dataRef = useRef<Record<string, unknown>>({});
128
-
129
- const updateData = useCallback((updates: Record<string, unknown>) => {
130
- const next = { ...dataRef.current, ...updates };
131
- dataRef.current = next;
132
- setData(next);
133
- setIsTouched(true);
134
- }, []);
135
-
136
- const validate = useCallback((validator: (data: Record<string, unknown>) => boolean) => {
137
- setIsValid(validator(dataRef.current));
138
- }, []);
139
-
140
- const reset = useCallback(() => {
141
- dataRef.current = {};
142
- setData({});
143
- setIsValid(false);
144
- setIsTouched(false);
145
- }, []);
146
-
147
- return {
148
- stepId,
149
- data,
150
- isValid,
151
- isTouched,
152
- updateData,
153
- validate,
154
- reset,
155
- };
156
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * @umituz/web-dashboard - Onboarding Domain
3
- *
4
- * Config-driven Onboarding System
5
- */
6
-
7
- export { OnboardingWizard } from './components';
8
- export { UserTypeStep } from './components';
9
- export { AppFocusStep } from './components';
10
- export { PlatformsStep } from './components';
11
- export { PlanStep } from './components';
12
- export { useOnboarding, useOnboardingStep } from './hooks';
13
- export {
14
- validateStep,
15
- getStepTitle,
16
- getStepDescription,
17
- calculateProgress,
18
- getCompletedSteps,
19
- formatOnboardingData,
20
- generateOnboardingEvent,
21
- isValidEmail,
22
- isValidPassword,
23
- ONBOARDING_KEYS,
24
- } from './utils';
25
- export type {
26
- UserTypeOption,
27
- PlatformOption,
28
- PlanOption,
29
- OnboardingStep,
30
- OnboardingConfig,
31
- OnboardingState,
32
- OnboardingActions,
33
- OnboardingWizardProps,
34
- StepProgressProps,
35
- StepNavigationProps,
36
- } from './types';
@@ -1,16 +0,0 @@
1
- /**
2
- * Onboarding Types Export
3
- */
4
-
5
- export type {
6
- UserTypeOption,
7
- PlatformOption,
8
- PlanOption,
9
- OnboardingStep,
10
- OnboardingConfig,
11
- OnboardingState,
12
- OnboardingActions,
13
- OnboardingWizardProps,
14
- StepProgressProps,
15
- StepNavigationProps,
16
- } from './onboarding';