@yogiswara/honcho-editor-ui 3.9.2 → 4.0.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.
@@ -0,0 +1,22 @@
1
+ import { type FC } from "react";
2
+ export interface AlbumSection {
3
+ id: string;
4
+ label: string;
5
+ description?: string;
6
+ }
7
+ interface Props {
8
+ sections: AlbumSection[];
9
+ activeSectionIndex: number;
10
+ onSectionChange: (index: number) => void;
11
+ onSectionsReorder: (reordered: AlbumSection[]) => void;
12
+ onAddSection: (name: string, description: string) => void;
13
+ onEditSection?: (index: number, name: string, description: string) => void;
14
+ onDeleteSection?: (sectionId: string) => void;
15
+ compact?: boolean;
16
+ selectedMode?: boolean;
17
+ onLoadMore?: () => void;
18
+ isLoadingMoreSections?: boolean;
19
+ hasMoreSections?: boolean;
20
+ }
21
+ declare const AlbumSectionTabs: FC<Props>;
22
+ export default AlbumSectionTabs;
@@ -0,0 +1,414 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useRef, useState, useEffect } from "react";
3
+ import { Box, Typography, Menu, MenuItem, TextField, Stack, Skeleton } from "@mui/material";
4
+ import useHonchoTypography from '../../../themes/honchoTheme';
5
+ import useColorsSecond from '../../../themes/colours';
6
+ import useIsMobile from '../../../utils/isMobile';
7
+ import IcPlusButton from "../svg/IcPlusButton";
8
+ import { IcChevronArrowDarkColor } from "../svg/IcChevron";
9
+ import { IcPencilIconDark } from "../svg/IcPencilIcon";
10
+ import { IcTrashIcon } from "../svg/IcTrashIcon";
11
+ import { HBaseDialog, NegativeButton, PositiveButton } from "../../editor/SectionAlbum/HBaseDialog";
12
+ const DRAG_THRESHOLD = 4;
13
+ const AlbumSectionTabs = ({ sections, activeSectionIndex, onSectionChange, onSectionsReorder, onAddSection, onEditSection, onDeleteSection, compact = false, onLoadMore, isLoadingMoreSections = false, hasMoreSections = false, }) => {
14
+ const isMobile = useIsMobile();
15
+ const colors = useColorsSecond();
16
+ const typography = useHonchoTypography();
17
+ // ---------- drag state ----------
18
+ const [dragIndex, setDragIndex] = useState(null);
19
+ const [overIndex, setOverIndex] = useState(null);
20
+ const [isDragging, setIsDragging] = useState(false);
21
+ const [cursorPos, setCursorPos] = useState({ x: 0, y: 0 });
22
+ const [openMenuIndex, setOpenMenuIndex] = useState(null);
23
+ const [menuAnchorEl, setMenuAnchorEl] = useState(null);
24
+ const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
25
+ const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
26
+ const [isCreateSectionDialogOpen, setIsCreateSectionDialogOpen] = useState(false);
27
+ const [selectedSectionIndex, setSelectedSectionIndex] = useState(null);
28
+ const [sectionName, setSectionName] = useState("");
29
+ const [sectionDescription, setSectionDescription] = useState("");
30
+ const pointerDownPos = useRef(null);
31
+ const pointerDownIndex = useRef(null);
32
+ const dragStarted = useRef(false);
33
+ const scrollRef = useRef(null);
34
+ const [canScrollLeft, setCanScrollLeft] = useState(false);
35
+ const [canScrollRight, setCanScrollRight] = useState(false);
36
+ // Prevents firing onLoadMore multiple times for the same scroll position
37
+ const isLoadingMoreRef = useRef(false);
38
+ const updateScrollButtons = () => {
39
+ const el = scrollRef.current;
40
+ if (!el)
41
+ return;
42
+ setCanScrollLeft(el.scrollLeft > 0);
43
+ setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
44
+ // Trigger load-more when within 80px of the right edge
45
+ const nearRightEdge = el.scrollLeft + el.clientWidth >= el.scrollWidth - 80;
46
+ if (nearRightEdge && hasMoreSections && !isLoadingMoreSections && !isLoadingMoreRef.current) {
47
+ isLoadingMoreRef.current = true;
48
+ onLoadMore?.();
49
+ }
50
+ if (!nearRightEdge) {
51
+ isLoadingMoreRef.current = false;
52
+ }
53
+ };
54
+ useEffect(() => {
55
+ updateScrollButtons();
56
+ const el = scrollRef.current;
57
+ if (!el)
58
+ return;
59
+ el.addEventListener("scroll", updateScrollButtons);
60
+ const ro = new ResizeObserver(updateScrollButtons);
61
+ ro.observe(el);
62
+ return () => {
63
+ el.removeEventListener("scroll", updateScrollButtons);
64
+ ro.disconnect();
65
+ };
66
+ }, [sections, hasMoreSections, isLoadingMoreSections]);
67
+ const scrollBy = (direction) => {
68
+ const el = scrollRef.current;
69
+ if (!el)
70
+ return;
71
+ el.scrollBy({ left: direction === "left" ? -160 : 160, behavior: "smooth" });
72
+ };
73
+ const activeSection = sections[activeSectionIndex]; // Get the current section
74
+ const handleEditSection = (index) => {
75
+ setOpenMenuIndex(null);
76
+ setMenuAnchorEl(null);
77
+ setSelectedSectionIndex(index);
78
+ setSectionName(sections[index].label);
79
+ setSectionDescription(sections[index].description || "");
80
+ setIsEditDialogOpen(true);
81
+ };
82
+ const handleDeleteSection = (index) => {
83
+ setOpenMenuIndex(null);
84
+ setMenuAnchorEl(null);
85
+ setSelectedSectionIndex(index);
86
+ setIsDeleteDialogOpen(true);
87
+ };
88
+ const handleCreateSection = () => {
89
+ setOpenMenuIndex(null);
90
+ setMenuAnchorEl(null);
91
+ setSectionName("");
92
+ setSectionDescription("");
93
+ setIsCreateSectionDialogOpen(true);
94
+ };
95
+ // ---------- pointer handlers ----------
96
+ const handlePointerDown = (e, index) => {
97
+ pointerDownPos.current = { x: e.clientX, y: e.clientY };
98
+ pointerDownIndex.current = index;
99
+ dragStarted.current = false;
100
+ e.currentTarget.setPointerCapture(e.pointerId);
101
+ };
102
+ const handlePointerMove = (e, index) => {
103
+ if (pointerDownPos.current === null)
104
+ return;
105
+ const dx = Math.abs(e.clientX - pointerDownPos.current.x);
106
+ const dy = Math.abs(e.clientY - pointerDownPos.current.y);
107
+ if (!dragStarted.current && (dx > DRAG_THRESHOLD || dy > DRAG_THRESHOLD)) {
108
+ dragStarted.current = true;
109
+ setDragIndex(pointerDownIndex.current);
110
+ setIsDragging(true);
111
+ }
112
+ if (dragStarted.current) {
113
+ setCursorPos({ x: e.clientX, y: e.clientY });
114
+ const elementUnderPointer = document.elementFromPoint(e.clientX, e.clientY);
115
+ if (elementUnderPointer) {
116
+ const tabNode = elementUnderPointer.closest('[data-index]');
117
+ if (tabNode) {
118
+ const hoveredIndex = parseInt(tabNode.getAttribute('data-index') || '-1', 10);
119
+ if (hoveredIndex !== -1 && hoveredIndex !== overIndex) {
120
+ setOverIndex(hoveredIndex);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ };
126
+ const handlePointerUp = (e, index) => {
127
+ if (!dragStarted.current) {
128
+ onSectionChange(index);
129
+ }
130
+ else if (dragIndex !== null && overIndex !== null && dragIndex !== overIndex) {
131
+ const reordered = [...sections];
132
+ const [moved] = reordered.splice(dragIndex, 1);
133
+ reordered.splice(overIndex, 0, moved);
134
+ let newActive = activeSectionIndex;
135
+ if (activeSectionIndex === dragIndex) {
136
+ newActive = overIndex;
137
+ }
138
+ else if (dragIndex < activeSectionIndex && overIndex >= activeSectionIndex) {
139
+ newActive = activeSectionIndex - 1;
140
+ }
141
+ else if (dragIndex > activeSectionIndex && overIndex <= activeSectionIndex) {
142
+ newActive = activeSectionIndex + 1;
143
+ }
144
+ onSectionsReorder(reordered);
145
+ onSectionChange(newActive);
146
+ }
147
+ setDragIndex(null);
148
+ setOverIndex(null);
149
+ setIsDragging(false);
150
+ dragStarted.current = false;
151
+ pointerDownPos.current = null;
152
+ pointerDownIndex.current = null;
153
+ };
154
+ const handlePointerCancel = () => {
155
+ setDragIndex(null);
156
+ setOverIndex(null);
157
+ setIsDragging(false);
158
+ dragStarted.current = false;
159
+ pointerDownPos.current = null;
160
+ pointerDownIndex.current = null;
161
+ };
162
+ useEffect(() => {
163
+ if (!scrollRef.current)
164
+ return;
165
+ const timeout = setTimeout(() => {
166
+ const activeTabNode = scrollRef.current?.querySelector(`[data-index="${activeSectionIndex}"]`);
167
+ if (activeTabNode) {
168
+ activeTabNode.scrollIntoView({
169
+ behavior: "smooth",
170
+ block: "nearest",
171
+ inline: "center",
172
+ });
173
+ }
174
+ }, 50);
175
+ return () => clearTimeout(timeout);
176
+ }, [activeSectionIndex]);
177
+ // ---------- render ----------
178
+ return (_jsxs(Box, { sx: {
179
+ // Removed the border from here, moved to the tab row so it sits above the description
180
+ ...(compact ? {
181
+ width: "100%",
182
+ } : {
183
+ width: "100vw",
184
+ position: "relative",
185
+ left: "50%",
186
+ right: "50%",
187
+ marginLeft: "-50vw",
188
+ marginRight: "-50vw",
189
+ }),
190
+ }, children: [_jsxs(Box, { sx: { position: "relative" }, children: [!isMobile && canScrollLeft && (_jsx(Box, { onClick: () => scrollBy("left"), sx: {
191
+ position: "absolute",
192
+ left: 0,
193
+ top: 0,
194
+ bottom: "1px",
195
+ zIndex: 2,
196
+ display: "flex",
197
+ alignItems: "center",
198
+ px: "4px",
199
+ pl: "24px",
200
+ cursor: "pointer",
201
+ background: colors.surface,
202
+ }, children: _jsx(IcChevronArrowDarkColor, { sx: {
203
+ width: "20px",
204
+ height: "20px",
205
+ color: colors.onSurface,
206
+ transform: "rotate(90deg)",
207
+ } }) })), !isMobile && canScrollRight && (_jsx(Box, { onClick: () => scrollBy("right"), sx: {
208
+ position: "absolute",
209
+ right: 0,
210
+ top: 0,
211
+ bottom: "1px",
212
+ zIndex: 2,
213
+ display: "flex",
214
+ alignItems: "center",
215
+ px: "4px",
216
+ pr: "24px",
217
+ cursor: "pointer",
218
+ background: colors.surface,
219
+ }, children: _jsx(IcChevronArrowDarkColor, { sx: {
220
+ width: "20px",
221
+ height: "20px",
222
+ color: colors.onSurface,
223
+ transform: "rotate(270deg)",
224
+ } }) })), _jsxs(Box, { ref: scrollRef, sx: {
225
+ display: "flex",
226
+ flexDirection: "row",
227
+ alignItems: "flex-end", // Aligns active bars to bottom
228
+ px: isMobile ? "16px" : "24px",
229
+ gap: "20px",
230
+ overflowX: "auto",
231
+ overflowY: "visible",
232
+ "&::-webkit-scrollbar": { display: "none" },
233
+ scrollbarWidth: "none",
234
+ userSelect: "none",
235
+ borderBottom: "1px solid", // Bottom border lives here now
236
+ borderColor: colors.outlineVariant,
237
+ }, children: [sections.map((section, index) => {
238
+ const isActive = index === activeSectionIndex;
239
+ const isBeingDragged = index === dragIndex;
240
+ const isDropTarget = index === overIndex && dragIndex !== null && dragIndex !== overIndex;
241
+ return (_jsxs(Box, { "data-index": index, onPointerDown: (e) => handlePointerDown(e, index), onPointerMove: (e) => handlePointerMove(e, index), onPointerUp: (e) => handlePointerUp(e, index), onPointerCancel: handlePointerCancel, sx: {
242
+ position: "relative",
243
+ overflow: "visible",
244
+ flexShrink: 0,
245
+ display: "flex",
246
+ alignItems: "center",
247
+ cursor: isDragging ? "grabbing" : "pointer",
248
+ height: "44px", // FIXED HEIGHT to ensure perfect alignment
249
+ boxSizing: "border-box",
250
+ px: "0px",
251
+ // active indicator
252
+ "&::after": {
253
+ content: '""',
254
+ position: "absolute",
255
+ bottom: "0px",
256
+ left: 0,
257
+ right: 0,
258
+ height: "1.5px",
259
+ backgroundColor: isActive ? colors.onSurface : "transparent",
260
+ transition: "background-color 0.15s ease",
261
+ },
262
+ // drop-target indicator
263
+ "&::before": isDropTarget
264
+ ? {
265
+ content: '""',
266
+ position: "absolute",
267
+ // Dynamic placement based on drag direction
268
+ left: dragIndex !== null && dragIndex > index ? "-10px" : "auto",
269
+ right: dragIndex !== null && dragIndex < index ? "-10px" : "auto",
270
+ top: "20%",
271
+ height: "60%",
272
+ width: "2px",
273
+ borderRadius: "2px",
274
+ backgroundColor: colors.onSurface,
275
+ }
276
+ : {},
277
+ opacity: isBeingDragged ? 0.35 : 1,
278
+ transform: isBeingDragged ? "scale(0.97)" : "scale(1)",
279
+ transition: "opacity 0.1s ease, transform 0.1s ease",
280
+ touchAction: "none",
281
+ }, children: [_jsx(Typography, { sx: {
282
+ ...typography.bodyMedium,
283
+ color: colors.onSurface,
284
+ opacity: isActive ? 1 : 0.6,
285
+ transition: "opacity 0.15s ease",
286
+ whiteSpace: "nowrap",
287
+ lineHeight: 1,
288
+ }, children: section.label }), _jsx(Box, { component: "span", className: "chevron-toggle", onPointerDown: (e) => {
289
+ e.stopPropagation();
290
+ }, onClick: (e) => {
291
+ e.stopPropagation();
292
+ if (openMenuIndex === index) {
293
+ setOpenMenuIndex(null);
294
+ setMenuAnchorEl(null);
295
+ }
296
+ else {
297
+ setOpenMenuIndex(index);
298
+ setMenuAnchorEl(e.currentTarget);
299
+ }
300
+ }, sx: { display: "flex", alignItems: "center", ml: "4px" }, children: _jsx(IcChevronArrowDarkColor, { sx: {
301
+ width: "16px",
302
+ height: "16px",
303
+ color: colors.onSurface,
304
+ opacity: (isActive || isMobile) ? 1 : 0,
305
+ visibility: isBeingDragged ? "hidden" : "visible",
306
+ transform: openMenuIndex === index ? 'rotate(180deg)' : 'rotate(0deg)',
307
+ transition: 'transform 0.2s ease, opacity 0.15s ease'
308
+ } }) })] }, section.id));
309
+ }), isLoadingMoreSections && (_jsx(Box, { sx: {
310
+ flexShrink: 0,
311
+ display: "flex",
312
+ alignItems: "center",
313
+ height: "44px",
314
+ px: "4px",
315
+ opacity: 0.4,
316
+ }, children: _jsx(Skeleton, { variant: "rectangular", width: 80, height: 24 }) })), _jsxs(Box, { onClick: handleCreateSection, sx: {
317
+ flexShrink: 0,
318
+ display: "flex",
319
+ alignItems: "center",
320
+ cursor: "pointer",
321
+ height: "44px", // FIXED HEIGHT matches the section tabs
322
+ boxSizing: "border-box",
323
+ px: "0px",
324
+ gap: "4px",
325
+ opacity: 0.5,
326
+ "&:hover": {
327
+ opacity: 1,
328
+ },
329
+ transition: "opacity 0.15s ease",
330
+ }, children: [_jsx(IcPlusButton, { sx: { width: "20px", height: "20px" } }), _jsx(Typography, { sx: {
331
+ ...typography.labelMedium,
332
+ color: colors.onSurface,
333
+ whiteSpace: "nowrap",
334
+ }, children: "Add section" })] })] })] }), activeSection?.description && (_jsx(Box, { sx: {
335
+ width: "100%",
336
+ px: isMobile ? "18px" : "24px",
337
+ pt: "32px", // Space between tabs and text
338
+ pb: "0px", // Tiny space before filter menu
339
+ }, children: _jsx(Typography, { sx: {
340
+ ...typography.bodyMedium,
341
+ color: colors.onSurface, // Subtle grey color for description
342
+ textAlign: "center",
343
+ whiteSpace: "pre-wrap"
344
+ }, children: activeSection.description }) })), _jsxs(Menu, { anchorEl: menuAnchorEl, open: Boolean(menuAnchorEl) && openMenuIndex !== null, onClose: () => {
345
+ setMenuAnchorEl(null);
346
+ setOpenMenuIndex(null);
347
+ }, slotProps: {
348
+ paper: {
349
+ sx: {
350
+ backgroundColor: colors.surface,
351
+ border: "1px solid",
352
+ borderColor: colors.outlineVariant,
353
+ borderRadius: "8px",
354
+ boxShadow: "0px 4px 12px rgba(0,0,0,0.08)",
355
+ minWidth: "105px",
356
+ mt: "4px",
357
+ }
358
+ }
359
+ }, children: [_jsxs(MenuItem, { onClick: () => {
360
+ if (openMenuIndex !== null)
361
+ handleEditSection(openMenuIndex);
362
+ }, sx: { display: "flex", alignItems: "center", py: "10px", px: "16px" }, children: [_jsx(IcPencilIconDark, { sx: { width: "20px", height: "20px", color: colors.onSurface, mr: "8px" } }), _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.onSurface }, children: "Edit" })] }), _jsxs(MenuItem, { onClick: () => {
363
+ if (openMenuIndex !== null)
364
+ handleDeleteSection(openMenuIndex);
365
+ }, sx: { display: "flex", alignItems: "center", py: "10px", px: "16px" }, children: [_jsx(IcTrashIcon, { sx: { width: "20px", height: "20px", color: colors.error, mr: "8px" } }), _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.error }, children: "Delete" })] })] }), isDragging && dragIndex !== null && (_jsx(Box, { sx: {
366
+ position: "fixed",
367
+ top: cursorPos.y - 14,
368
+ left: cursorPos.x + 12,
369
+ pointerEvents: "none",
370
+ zIndex: 9999,
371
+ backgroundColor: colors.surface,
372
+ border: "1px solid",
373
+ borderColor: colors.outlineVariant,
374
+ borderRadius: "6px",
375
+ px: "10px",
376
+ py: "6px",
377
+ boxShadow: "0px 4px 12px rgba(0,0,0,0.12)",
378
+ display: "flex",
379
+ alignItems: "center",
380
+ gap: "6px",
381
+ }, children: _jsx(Typography, { sx: {
382
+ ...typography.bodyMedium,
383
+ color: colors.onSurface,
384
+ lineHeight: 1,
385
+ whiteSpace: "nowrap",
386
+ }, children: sections[dragIndex]?.label }) })), isCreateSectionDialogOpen && (_jsx(HBaseDialog, { title: "Add section", description:
387
+ // ADDED onKeyDown to stop propagation to the background gallery
388
+ _jsxs(Stack, { spacing: "12px", onKeyDown: (e) => e.stopPropagation(), children: [_jsxs(Box, { sx: { backgroundColor: colors.onSurfaceVariant2, py: "8px", px: "16px", borderRadius: "4px" }, children: [_jsx(Typography, { sx: { ...typography.bodySmall, color: colors.onSurfaceVariant1 }, children: "Section name" }), _jsx(TextField, { autoFocus: true, placeholder: "Enter section name", type: "text", fullWidth: true, variant: "standard", InputProps: { disableUnderline: true }, value: sectionName, onChange: (e) => setSectionName(e.target.value), sx: { "& .MuiInputBase-input": { padding: 0, marginTop: "4px", ...typography.bodyMedium } } })] }), _jsxs(Box, { sx: { backgroundColor: colors.onSurfaceVariant2, py: "8px", px: "16px", borderRadius: "4px" }, children: [_jsx(Typography, { sx: { ...typography.bodySmall, color: colors.onSurfaceVariant1 }, children: "Description (Optional)" }), _jsx(TextField, { placeholder: "Add a description...", type: "text", fullWidth: true, multiline: true, rows: 3, variant: "standard", InputProps: { disableUnderline: true }, value: sectionDescription, onChange: (e) => setSectionDescription(e.target.value), sx: { "& .MuiInputBase-input": { padding: 0, marginTop: "4px", ...typography.bodyMedium } } })] })] }), action: _jsxs(_Fragment, { children: [_jsx(PositiveButton, { text: "Cancel", onClick: () => setIsCreateSectionDialogOpen(false) }), _jsx(PositiveButton, { text: "Save", disabled: !sectionName.trim(), onClick: () => {
389
+ onAddSection(sectionName, sectionDescription);
390
+ setIsCreateSectionDialogOpen(false);
391
+ } })] }) })), isEditDialogOpen && selectedSectionIndex !== null && (_jsx(HBaseDialog, { title: "Edit section", description:
392
+ // ADDED onKeyDown to stop propagation to the background gallery
393
+ _jsxs(Stack, { spacing: "12px", onKeyDown: (e) => e.stopPropagation(), children: [_jsxs(Box, { sx: { backgroundColor: colors.onSurfaceVariant2, py: "8px", px: "16px", borderRadius: "4px" }, children: [_jsx(Typography, { sx: { ...typography.bodySmall, color: colors.onSurfaceVariant1 }, children: "Section name" }), _jsx(TextField, { autoFocus: true, placeholder: "Enter section name", type: "text", fullWidth: true, variant: "standard", InputProps: { disableUnderline: true }, value: sectionName, onChange: (e) => setSectionName(e.target.value), sx: { "& .MuiInputBase-input": { padding: 0, marginTop: "4px", ...typography.bodyMedium } } })] }), _jsxs(Box, { sx: { backgroundColor: colors.onSurfaceVariant2, py: "8px", px: "16px", borderRadius: "4px" }, children: [_jsx(Typography, { sx: { ...typography.bodySmall, color: colors.onSurfaceVariant1 }, children: "Description (Optional)" }), _jsx(TextField, { placeholder: "Add a description...", type: "text", fullWidth: true, multiline: true, rows: 3, variant: "standard", InputProps: { disableUnderline: true }, value: sectionDescription, onChange: (e) => setSectionDescription(e.target.value), sx: { "& .MuiInputBase-input": { padding: 0, marginTop: "4px", ...typography.bodyMedium } } })] })] }), action: _jsxs(_Fragment, { children: [_jsx(PositiveButton, { text: "Cancel", onClick: () => setIsEditDialogOpen(false) }), _jsx(PositiveButton, { text: "Save", disabled: !sectionName.trim(), onClick: () => {
394
+ if (onEditSection) {
395
+ onEditSection(selectedSectionIndex, sectionName, sectionDescription);
396
+ }
397
+ setIsEditDialogOpen(false);
398
+ } })] }) })), isDeleteDialogOpen && selectedSectionIndex !== null && (_jsx(HBaseDialog, { title: "Delete section?", description: "Permanently delete this section and its photos.", action: _jsxs(_Fragment, { children: [_jsx(PositiveButton, { text: "Cancel", onClick: () => setIsDeleteDialogOpen(false) }), _jsx(NegativeButton, { text: "Delete", onClick: () => {
399
+ // 1. Fire the actual delete function
400
+ if (onDeleteSection) {
401
+ onDeleteSection(sections[selectedSectionIndex].id);
402
+ }
403
+ // 2. Adjust the active tab if you are deleting the one you are currently viewing
404
+ const reorderedLength = sections.length - 1;
405
+ const newActive = activeSectionIndex >= reorderedLength
406
+ ? Math.max(0, reorderedLength - 1)
407
+ : activeSectionIndex === selectedSectionIndex
408
+ ? Math.max(0, selectedSectionIndex - 1)
409
+ : activeSectionIndex;
410
+ onSectionChange(newActive);
411
+ setIsDeleteDialogOpen(false);
412
+ } })] }) }))] }));
413
+ };
414
+ export default AlbumSectionTabs;
@@ -0,0 +1,14 @@
1
+ import { type FC } from "react";
2
+ import { AlbumSection } from "./AlbumSectionTabs";
3
+ interface Props {
4
+ sections: AlbumSection[];
5
+ activeSectionIndex: number;
6
+ onSectionChange: (index: number) => void;
7
+ selectedCounts?: Record<string, number>;
8
+ onLoadMore?: () => void;
9
+ isLoadingMoreSections?: boolean;
10
+ hasMoreSections?: boolean;
11
+ isEditorSelectionMode?: boolean;
12
+ }
13
+ declare const AlbumSectionTabsSelectMode: FC<Props>;
14
+ export default AlbumSectionTabsSelectMode;
@@ -0,0 +1,180 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRef, useState, useEffect } from "react";
3
+ import { Box, Typography, Skeleton } from "@mui/material"; // Added Skeleton
4
+ import useHonchoTypography from '../../../themes/honchoTheme';
5
+ import useColors from '../../../themes/colors';
6
+ import useIsMobile from '../../../utils/isMobile';
7
+ import { IcChevronArrowDarkColor, IcChevronArrowLightColor } from "../svg/IcChevron";
8
+ const AlbumSectionTabsSelectMode = ({ sections, activeSectionIndex, onSectionChange, selectedCounts = {}, onLoadMore, isLoadingMoreSections = false, hasMoreSections = false, isEditorSelectionMode = false, }) => {
9
+ const isMobile = useIsMobile();
10
+ const colors = useColors();
11
+ const typography = useHonchoTypography();
12
+ // --- Pagination / Scroll Logic ---
13
+ const scrollRef = useRef(null);
14
+ const [showLeftButton, setShowLeftButton] = useState(false);
15
+ const [showRightButton, setShowRightButton] = useState(false);
16
+ // NEW: Prevent firing multiple load requests at the same scroll position
17
+ const isLoadingMoreRef = useRef(false);
18
+ const checkScrollButtons = () => {
19
+ const el = scrollRef.current;
20
+ if (!el)
21
+ return;
22
+ const { scrollLeft, scrollWidth, clientWidth } = el;
23
+ setShowLeftButton(scrollLeft > 0);
24
+ setShowRightButton(Math.ceil(scrollLeft + clientWidth) < scrollWidth);
25
+ // NEW: Trigger load-more when within 80px of the right edge
26
+ const nearRightEdge = scrollLeft + clientWidth >= scrollWidth - 80;
27
+ if (nearRightEdge && hasMoreSections && !isLoadingMoreSections && !isLoadingMoreRef.current) {
28
+ isLoadingMoreRef.current = true;
29
+ if (onLoadMore)
30
+ onLoadMore();
31
+ }
32
+ if (!nearRightEdge) {
33
+ isLoadingMoreRef.current = false;
34
+ }
35
+ };
36
+ useEffect(() => {
37
+ checkScrollButtons();
38
+ window.addEventListener("resize", checkScrollButtons);
39
+ return () => window.removeEventListener("resize", checkScrollButtons);
40
+ }, [sections, hasMoreSections, isLoadingMoreSections]);
41
+ const handleScroll = (direction) => {
42
+ if (scrollRef.current) {
43
+ const scrollAmount = 200;
44
+ scrollRef.current.scrollBy({
45
+ left: direction === "left" ? -scrollAmount : scrollAmount,
46
+ behavior: "smooth",
47
+ });
48
+ }
49
+ };
50
+ const onScroll = () => {
51
+ checkScrollButtons();
52
+ };
53
+ // Auto-scroll to active tab when changed
54
+ useEffect(() => {
55
+ if (!scrollRef.current)
56
+ return;
57
+ const timeout = setTimeout(() => {
58
+ const activeTabNode = scrollRef.current?.querySelector(`[data-index="${activeSectionIndex}"]`);
59
+ if (activeTabNode) {
60
+ activeTabNode.scrollIntoView({
61
+ behavior: "smooth",
62
+ block: "nearest",
63
+ inline: "center",
64
+ });
65
+ }
66
+ }, 50);
67
+ return () => clearTimeout(timeout);
68
+ }, [activeSectionIndex]);
69
+ return (_jsxs(Box, { sx: {
70
+ borderBottom: "1px solid",
71
+ borderColor: isEditorSelectionMode ? colors.onSurfaceVariantDark : colors.outlineVariant,
72
+ width: "100vw",
73
+ position: "relative",
74
+ left: "50%",
75
+ right: "50%",
76
+ marginLeft: "-50vw",
77
+ marginRight: "-50vw",
78
+ backgroundColor: isEditorSelectionMode ? colors.onBackground : colors.surface,
79
+ display: "flex",
80
+ alignItems: "center",
81
+ }, children: [!isMobile && showLeftButton && (_jsx(Box, { sx: {
82
+ position: "absolute",
83
+ left: 0,
84
+ top: 0,
85
+ bottom: "1px",
86
+ display: "flex",
87
+ alignItems: "center",
88
+ background: isEditorSelectionMode ? colors.onBackground : colors.surface,
89
+ paddingRight: "24px",
90
+ paddingLeft: "16px",
91
+ zIndex: 2,
92
+ }, children: isEditorSelectionMode ?
93
+ _jsx(IcChevronArrowLightColor, { sx: {
94
+ width: "20px",
95
+ height: "20px",
96
+ color: colors.onSurface,
97
+ transform: "rotate(180deg)",
98
+ } }) :
99
+ _jsx(IcChevronArrowDarkColor, { sx: {
100
+ width: "20px",
101
+ height: "20px",
102
+ color: colors.onSurface,
103
+ transform: "rotate(90deg)",
104
+ } }) })), _jsxs(Box, { ref: scrollRef, onScroll: onScroll, sx: {
105
+ display: "flex",
106
+ flexDirection: "row",
107
+ alignItems: "flex-end",
108
+ px: isMobile ? "18px" : "24px",
109
+ gap: "24px",
110
+ overflowX: "auto",
111
+ width: "100%",
112
+ "&::-webkit-scrollbar": { display: "none" },
113
+ msOverflowStyle: "none",
114
+ scrollbarWidth: "none",
115
+ }, children: [sections.map((section, index) => {
116
+ const isActive = index === activeSectionIndex;
117
+ const selectedCount = selectedCounts[section.id] || 0;
118
+ return (_jsxs(Box, { "data-index": index, onClick: () => onSectionChange(index), sx: {
119
+ display: "flex",
120
+ alignItems: "center",
121
+ pb: "12px",
122
+ pt: "12px",
123
+ cursor: "pointer",
124
+ borderBottom: isActive ? "2px solid" : "2px solid transparent",
125
+ borderColor: (isEditorSelectionMode ? (isActive ? colors.background : "transparent") : (isActive ? colors.onSurface : "transparent")),
126
+ whiteSpace: "nowrap",
127
+ transition: "all 0.2s ease-in-out",
128
+ }, children: [_jsx(Typography, { sx: {
129
+ ...typography.bodyMedium,
130
+ color: (isEditorSelectionMode ? (isActive ? colors.background : colors.background) : (isActive ? colors.onSurface : colors.onSurfaceVariant1)),
131
+ }, children: section.label }), selectedCount > 0 && (_jsx(Box, { sx: {
132
+ ml: "6px",
133
+ backgroundColor: isEditorSelectionMode ? colors.background : colors.onSurface,
134
+ color: isEditorSelectionMode ? colors.onSurface : colors.surface,
135
+ borderRadius: "10px",
136
+ minWidth: "18px",
137
+ height: "18px",
138
+ display: "flex",
139
+ alignItems: "center",
140
+ justifyContent: "center",
141
+ px: "5px",
142
+ }, children: _jsx(Typography, { sx: {
143
+ ...typography.labelSmall,
144
+ color: isEditorSelectionMode ? colors.onSurface : colors.surface,
145
+ lineHeight: 1,
146
+ fontSize: "11px",
147
+ // fontWeight: 600,
148
+ }, children: selectedCount }) }))] }, section.id));
149
+ }), isLoadingMoreSections && (_jsx(Box, { sx: {
150
+ flexShrink: 0,
151
+ display: "flex",
152
+ alignItems: "center",
153
+ height: "44px",
154
+ px: "4px",
155
+ opacity: 0.4,
156
+ }, children: _jsx(Skeleton, { variant: "rectangular", width: 80, height: 24 }) }))] }), !isMobile && showRightButton && (_jsx(Box, { onClick: () => handleScroll("right"), sx: {
157
+ position: "absolute",
158
+ right: 0,
159
+ top: 0,
160
+ bottom: "1px",
161
+ display: "flex",
162
+ alignItems: "center",
163
+ background: isEditorSelectionMode ? colors.onBackground : colors.surface,
164
+ paddingLeft: "24px",
165
+ paddingRight: "16px",
166
+ zIndex: 2,
167
+ }, children: isEditorSelectionMode ?
168
+ _jsx(IcChevronArrowLightColor, { sx: {
169
+ width: "20px",
170
+ height: "20px",
171
+ color: colors.onSurface,
172
+ } }) :
173
+ _jsx(IcChevronArrowDarkColor, { sx: {
174
+ width: "20px",
175
+ height: "20px",
176
+ color: colors.onSurface,
177
+ transform: "rotate(270deg)",
178
+ } }) }))] }));
179
+ };
180
+ export default AlbumSectionTabsSelectMode;
@@ -0,0 +1,24 @@
1
+ import React, { ReactElement } from "react";
2
+ interface Props {
3
+ title: React.ReactNode;
4
+ description: React.ReactNode | ReactElement;
5
+ onClose?: () => void;
6
+ action?: React.ReactNode;
7
+ paddingTop?: string;
8
+ hasFullWidthContent?: boolean;
9
+ isCentered?: boolean;
10
+ }
11
+ export declare function HBaseDialog(props: Props): import("react/jsx-runtime").JSX.Element;
12
+ export declare function HBaseDialogMiddle(props: Props): import("react/jsx-runtime").JSX.Element;
13
+ interface ButtonProps {
14
+ text: string;
15
+ onClick: () => void;
16
+ color?: string;
17
+ backgroundColor?: string;
18
+ backgroundColorHover?: string;
19
+ padding?: string;
20
+ disabled?: boolean;
21
+ }
22
+ export declare function PositiveButton(props: ButtonProps): import("react/jsx-runtime").JSX.Element;
23
+ export declare function NegativeButton(props: ButtonProps): import("react/jsx-runtime").JSX.Element;
24
+ export {};
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Dialog, DialogActions, DialogContent, IconButton, Stack, Typography, Box, } from "@mui/material";
3
+ import useColors from '../../../themes/colors';
4
+ import { CloseOutlined } from "@mui/icons-material";
5
+ export function HBaseDialog(props) {
6
+ const colors = useColors();
7
+ return (_jsxs(Dialog, { disableScrollLock: true, open: true, onClose: () => { }, "aria-labelledby": "responsive-dialog-title", PaperProps: {
8
+ sx: {
9
+ borderRadius: "28px",
10
+ // Shrink the max-width and width if it is centered
11
+ maxWidth: props.isCentered
12
+ ? { xs: 328, sm: "260px", md: "260px" }
13
+ : { xs: 328, sm: "456px", md: "456px" },
14
+ width: props.isCentered
15
+ ? { xs: "328px", sm: "260px", md: "260px" }
16
+ : { xs: "328px", sm: "456px", md: "456px" },
17
+ margin: { xs: 0, sm: "auto" },
18
+ },
19
+ }, children: [_jsx(DialogContent, { sx: { padding: props.hasFullWidthContent
20
+ ? { xs: "24px 0 0 0", sm: "24px 0 0 0" }
21
+ : { xs: "24px 24px 0 24px", sm: "24px 24px 0 24px" }
22
+ }, children: _jsxs(Stack, { spacing: 2, direction: "column", children: [_jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: props.isCentered ? "center" : "space-between", position: props.isCentered ? "relative" : undefined, sx: {
23
+ px: props.hasFullWidthContent
24
+ ? { xs: "24px", sm: "24px" }
25
+ : 0
26
+ }, children: [_jsx(Typography, { color: colors.onSurface, textAlign: props.isCentered ? "center" : "left", variant: "labelLarge", children: props.title }), props.onClose && (props.isCentered ? (_jsx(Box, { sx: { position: "absolute", right: 0 }, children: _jsx(CloseButton, { onClick: props.onClose }) })) : (_jsx(CloseButton, { onClick: props.onClose })))] }), _jsx(Typography, { variant: "bodyMedium", textAlign: props.isCentered ? "center" : "left", color: colors.onSurface, children: props.description })] }) }), props.action && (_jsx(DialogActions, { sx: { padding: 3, pt: props.paddingTop || "24px" }, children: _jsx(Stack, { direction: "row", justifyContent: props.isCentered ? "center" : "flex-end", alignItems: "center", gap: 1, sx: props.isCentered ? { width: "100%" } : {}, children: props.action }) }))] }));
27
+ }
28
+ export function HBaseDialogMiddle(props) {
29
+ const colors = useColors();
30
+ return (_jsx(Dialog, { disableScrollLock: true, open: true, onClose: () => { }, "aria-labelledby": "responsive-dialog-title", PaperProps: {
31
+ sx: {
32
+ borderRadius: "28px",
33
+ maxWidth: { xs: 328, sm: "456px", md: "456px" },
34
+ width: { xs: "328px", sm: "456px", md: "456px" },
35
+ //maxHeight: 306,
36
+ margin: { xs: 0, sm: "auto" },
37
+ pb: "24px"
38
+ },
39
+ }, children: _jsx(DialogContent, { sx: { padding: props.hasFullWidthContent
40
+ ? { xs: "24px 0 0 0", sm: "24px 0 0 0" }
41
+ : { xs: "24px 24px 0 24px", sm: "24px 24px 0 24px" }
42
+ }, children: _jsxs(Stack, { spacing: 2, direction: "column", alignItems: "center", children: [_jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: props.onClose ? "space-between" : "center", sx: {
43
+ px: props.hasFullWidthContent
44
+ ? { xs: "24px", sm: "24px" }
45
+ : 0,
46
+ width: "100%"
47
+ }, children: [_jsx(Typography, { color: colors.onSurface, variant: "labelLarge", children: props.title }), props.onClose && (_jsx(CloseButton, { onClick: props.onClose }))] }), _jsx(Typography, { variant: "bodyMedium", color: colors.onSurface, textAlign: "center", children: props.description }), props.action && (_jsx(Stack, { direction: "row", justifyContent: "center", alignItems: "center", gap: 1, sx: { pt: 1 }, children: props.action }))] }) }) }));
48
+ }
49
+ export function PositiveButton(props) {
50
+ const colors = useColors();
51
+ return (_jsx(Button, { variant: "text", disabled: props.disabled, sx: {
52
+ padding: props.padding,
53
+ ":hover": {
54
+ backgroundColor: "transparent",
55
+ },
56
+ }, onClick: props.onClick, children: _jsx(Typography, { variant: "buttonMedium",
57
+ // Change color if disabled so the UI reflects the locked state
58
+ color: props.disabled ? "text.disabled" : colors.onSurface, children: props.text }) }));
59
+ }
60
+ export function NegativeButton(props) {
61
+ const colors = useColors();
62
+ return (_jsx(Button, { variant: "text", disabled: props.disabled, sx: {
63
+ borderRadius: 100,
64
+ // Change color if disabled so the UI reflects the locked state
65
+ color: props.disabled ? "text.disabled" : (props.color || colors.error),
66
+ backgroundColor: props.backgroundColor || "transparent",
67
+ padding: props.padding,
68
+ ":hover": {
69
+ backgroundColor: props.backgroundColorHover || "transparent",
70
+ },
71
+ }, onClick: props.onClick, children: props.text }));
72
+ }
73
+ function CloseButton(props) {
74
+ return (_jsx(IconButton, { onClick: props.onClick, children: _jsx(CloseOutlined, { htmlColor: "black" }) }));
75
+ }
@@ -0,0 +1,5 @@
1
+ import { SvgIconProps } from '@mui/material';
2
+ export declare function IcChevronDown(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function IcChevronUp(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function IcChevronArrowDarkColor(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
5
+ export declare function IcChevronArrowLightColor(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { SvgIcon } from '@mui/material';
3
+ export function IcChevronDown(props) {
4
+ return (_jsx(SvgIcon, { ...props, viewBox: "0 0 20 20", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M4.16406 7.5L9.9974 13.3333L15.8307 7.5", stroke: "#656369", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
5
+ }
6
+ ;
7
+ export function IcChevronUp(props) {
8
+ return (_jsx(SvgIcon, { ...props, viewBox: "0 0 20 20", children: _jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("g", { clipPath: "url(#clip0_25667_16969)", children: _jsx("path", { d: "M9.9974 1.66797C12.0818 3.94993 13.2664 6.91133 13.3307 10.0013C13.2664 13.0913 12.0818 16.0527 9.9974 18.3346M9.9974 1.66797C7.913 3.94993 6.72844 6.91133 6.66406 10.0013C6.72844 13.0913 7.913 16.0527 9.9974 18.3346M9.9974 1.66797C5.39502 1.66797 1.66406 5.39893 1.66406 10.0013C1.66406 14.6037 5.39502 18.3346 9.9974 18.3346M9.9974 1.66797C14.5998 1.66797 18.3307 5.39893 18.3307 10.0013C18.3307 14.6037 14.5998 18.3346 9.9974 18.3346M2.08075 7.5013H17.9141M2.08073 12.5013H17.9141", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }), _jsx("defs", { children: _jsx("clipPath", { id: "clip0_25667_16969", children: _jsx("rect", { width: "20", height: "20", fill: "white" }) }) })] }) }));
9
+ }
10
+ export function IcChevronArrowDarkColor(props) {
11
+ return (_jsx(SvgIcon, { ...props, viewBox: "0 0 20 20", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M4.16406 7.5L9.9974 13.3333L15.8307 7.5", stroke: "#1C1B1F", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
12
+ }
13
+ export function IcChevronArrowLightColor(props) {
14
+ return (_jsx(SvgIcon, { ...props, viewBox: "0 0 20 20", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M7.5 15.8307L13.3333 9.9974L7.5 4.16406", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
15
+ }
@@ -0,0 +1,3 @@
1
+ import { SvgIconProps } from '@mui/material';
2
+ export declare function IcPencilIconWhite(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function IcPencilIconDark(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { SvgIcon } from '@mui/material';
3
+ export function IcPencilIconWhite(props) {
4
+ return (_jsx(SvgIcon, { ...props, viewBox: "0 0 20 20", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M14.5289 8.57532L11.4247 5.47109M2.5 17.5L5.12647 17.2082C5.44736 17.1725 5.6078 17.1547 5.75777 17.1061C5.89082 17.0631 6.01744 17.0022 6.13419 16.9252C6.26579 16.8384 6.37994 16.7243 6.60824 16.496L16.8571 6.24715C17.7143 5.38993 17.7143 4.00012 16.8571 3.14291C15.9999 2.2857 14.6101 2.2857 13.7529 3.14291L3.50401 13.3918C3.27571 13.6201 3.16155 13.7342 3.07478 13.8658C2.99779 13.9826 2.93693 14.1092 2.89386 14.2422C2.84531 14.3922 2.82748 14.5526 2.79183 14.8735L2.5 17.5Z", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
5
+ }
6
+ ;
7
+ export function IcPencilIconDark(props) {
8
+ return (_jsx(SvgIcon, { ...props, viewBox: "0 0 20 20", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M14.5289 8.57532L11.4247 5.47109M2.5 17.5L5.12647 17.2082C5.44736 17.1725 5.6078 17.1547 5.75777 17.1061C5.89082 17.0631 6.01744 17.0022 6.13419 16.9252C6.26579 16.8384 6.37994 16.7243 6.60824 16.496L16.8571 6.24715C17.7143 5.38993 17.7143 4.00012 16.8571 3.14291C15.9999 2.2857 14.6101 2.2857 13.7529 3.14291L3.50401 13.3918C3.27571 13.6201 3.16155 13.7342 3.07478 13.8658C2.99779 13.9826 2.93693 14.1092 2.89386 14.2422C2.84531 14.3922 2.82748 14.5526 2.79183 14.8735L2.5 17.5Z", stroke: "#1C1B1F", strokeWidth: "1.25", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
9
+ }
10
+ ;
@@ -0,0 +1,2 @@
1
+ import { SvgIconOwnProps } from "@mui/material";
2
+ export default function IcPlusButton(props: SvgIconOwnProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { SvgIcon } from "@mui/material";
3
+ export default function IcPlusButton(props) {
4
+ return (_jsx(SvgIcon, { ...props, children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M10.0013 4.16602V15.8327M4.16797 9.99935H15.8346", stroke: "#1C1B1F", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
5
+ }
@@ -0,0 +1,2 @@
1
+ import { SvgIconProps } from '@mui/material';
2
+ export declare function IcTrashIcon(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { SvgIcon } from '@mui/material';
3
+ export function IcTrashIcon(props) {
4
+ return (_jsx(SvgIcon, { ...props, viewBox: "0 0 20 20", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M7.5 2.5H12.5M2.5 5H17.5M15.8333 5L15.2489 13.7661C15.1612 15.0813 15.1174 15.7389 14.8333 16.2375C14.5833 16.6765 14.206 17.0294 13.7514 17.2497C13.235 17.5 12.5759 17.5 11.2578 17.5H8.74221C7.42409 17.5 6.76503 17.5 6.24861 17.2497C5.79396 17.0294 5.41674 16.6765 5.16665 16.2375C4.88259 15.7389 4.83875 15.0813 4.75107 13.7661L4.16667 5", stroke: "#DC362E", strokeWidth: "1.25", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
5
+ }
6
+ ;
package/dist/index.d.ts CHANGED
@@ -35,11 +35,14 @@ export { default as HModalDialog } from './components/modal/HModalDialog';
35
35
  export { default as HModalRename } from './components/modal/HModalRename';
36
36
  export { default as HTabColorAdjustmentMobile } from './components/editor/HTabColorAdjustmentMobile';
37
37
  export { default as HTabPresetMobile } from './components/editor/HTabPresetMobile';
38
+ export { default as AlbumSectionTabsSelectMode } from './components/editor/SectionAlbum/AlbumSectionTabsSelectMode';
39
+ export { default as AlbumSectionTabs } from './components/editor/SectionAlbum/AlbumSectionTabs';
38
40
  export { useAdjustmentHistory, type UseAdjustmentHistoryReturn, type HistoryInfo, type HistoryActions, type HistoryConfig } from './hooks/useAdjustmentHistory';
39
41
  export { useAdjustmentHistoryBatch, type UseAdjustmentHistoryBatchReturn, type BatchAdjustmentState, type ImageAdjustmentConfig, type BatchHistoryActions, type BatchHistoryState, type HistoryAdjustmentBatch, type HistoryAdjustmentEntry } from './hooks/useAdjustmentHistoryBatch';
40
42
  export { usePreset, type UsePresetReturn, type PresetInfo, type PresetActions, type PresetOptions } from './hooks/usePreset';
41
43
  export { usePaging, type UsePagingReturn, type PagingInfo, type PagingActions, type PagingOptions } from './hooks/usePaging';
42
44
  export { default as useColors } from './themes/colors';
45
+ export { default as useColorsSecond } from './themes/colours';
43
46
  export { default as useHonchoTypography } from './themes/honchoTheme';
44
47
  export { default as useIsMobile } from './utils/isMobile';
45
48
  export { default as useSliderEvents } from './components/editor/sliderComponents/useSliderEvents';
package/dist/index.js CHANGED
@@ -37,6 +37,8 @@ export { default as HModalDialog } from './components/modal/HModalDialog';
37
37
  export { default as HModalRename } from './components/modal/HModalRename';
38
38
  export { default as HTabColorAdjustmentMobile } from './components/editor/HTabColorAdjustmentMobile';
39
39
  export { default as HTabPresetMobile } from './components/editor/HTabPresetMobile';
40
+ export { default as AlbumSectionTabsSelectMode } from './components/editor/SectionAlbum/AlbumSectionTabsSelectMode';
41
+ export { default as AlbumSectionTabs } from './components/editor/SectionAlbum/AlbumSectionTabs';
40
42
  // --- History Hooks ---
41
43
  export { useAdjustmentHistory } from './hooks/useAdjustmentHistory';
42
44
  export { useAdjustmentHistoryBatch } from './hooks/useAdjustmentHistoryBatch';
@@ -46,6 +48,7 @@ export { usePreset } from './hooks/usePreset';
46
48
  export { usePaging } from './hooks/usePaging';
47
49
  // --- Theme & Utils ---
48
50
  export { default as useColors } from './themes/colors';
51
+ export { default as useColorsSecond } from './themes/colours';
49
52
  export { default as useHonchoTypography } from './themes/honchoTheme';
50
53
  export { default as useIsMobile } from './utils/isMobile';
51
54
  export { default as useSliderEvents } from './components/editor/sliderComponents/useSliderEvents';
@@ -3,10 +3,12 @@ interface Colors {
3
3
  surface: string;
4
4
  onSurfaceVariant: string;
5
5
  onSurfaceVariant1: string;
6
+ onSurfaceVariantDark: string;
6
7
  outlineVariant: string;
7
8
  error: string;
8
9
  onBackground: string;
9
10
  background: string;
11
+ surfaceVariant2: string;
10
12
  }
11
13
  export default function useColors(): Colors;
12
14
  export {};
@@ -4,9 +4,11 @@ export default function useColors() {
4
4
  surface: "#FFFFFF",
5
5
  onSurfaceVariant: "#949494",
6
6
  onSurfaceVariant1: "#656369",
7
+ onSurfaceVariantDark: "#2E2E2E",
7
8
  outlineVariant: "#EDEDED",
8
9
  error: "#DC362E",
9
10
  onBackground: "#000000",
10
- background: "#FFFFFF"
11
+ background: "#FFFFFF",
12
+ surfaceVariant2: "#F6F6F6"
11
13
  };
12
14
  }
@@ -0,0 +1,14 @@
1
+ interface Colors {
2
+ onSurface: string;
3
+ surface: string;
4
+ onSurfaceVariant: string;
5
+ onSurfaceVariant1: string;
6
+ onSurfaceVariant2: string;
7
+ onSurfaceVariantDark: string;
8
+ outlineVariant: string;
9
+ error: string;
10
+ onBackground: string;
11
+ background: string;
12
+ }
13
+ export default function useColorsSecond(): Colors;
14
+ export {};
@@ -0,0 +1,14 @@
1
+ export default function useColorsSecond() {
2
+ return {
3
+ onSurface: "#1C1B1F",
4
+ surface: "#FFFFFF",
5
+ onSurfaceVariant: "#949494",
6
+ onSurfaceVariant1: "#656369",
7
+ onSurfaceVariant2: "#F6F6F6",
8
+ onSurfaceVariantDark: "#2E2E2E",
9
+ outlineVariant: "#EDEDED",
10
+ error: "#DC362E",
11
+ onBackground: "#000000",
12
+ background: "#FFFFFF"
13
+ };
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yogiswara/honcho-editor-ui",
3
- "version": "3.9.2",
3
+ "version": "4.0.0",
4
4
  "description": "A complete UI component library for the Honcho photo editor.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",