@coyalabs/bts-style 1.3.8 → 1.3.10

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 (2) hide show
  1. package/README.md +1465 -0
  2. package/package.json +5 -3
package/README.md ADDED
@@ -0,0 +1,1465 @@
1
+ # @coyalabs/bts-style
2
+
3
+ **Coya Behind the Scenes** - A Svelte 4 component library with a serif 1920s aesthetic.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @coyalabs/bts-style
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```svelte
14
+ <script>
15
+ import { BasePage, Button, BaseText } from '@coyalabs/bts-style';
16
+ </script>
17
+
18
+ <BasePage>
19
+ <BaseText variant="title">Hello BTS Theme!</BaseText>
20
+ <Button theme="primary">Click Me</Button>
21
+ </BasePage>
22
+ ```
23
+
24
+ ## Design System
25
+
26
+ ### Colors
27
+
28
+ - **Background:** `#0B070D` - Deep dark page background
29
+ - **Default Text:** `#E3D8D8` - Light text and icons
30
+ - **Toned:** `#A18F8F` - Muted icons and accents
31
+ - **Accent:** `#FFEFF6` - Interactive elements
32
+
33
+ ### Fonts
34
+
35
+ The package uses fonts from Google Fonts and Fontshare (loaded via CDN):
36
+ - **Noto Serif KR (900)** - Titles and button text
37
+ - **Satoshi (400, 500, 700, 900)** - Content and UI text
38
+
39
+ ### Theme Variants
40
+
41
+ All container-based components support these themes:
42
+
43
+ - **`full`** - Standard glass container with subtle background
44
+ - **`primary`** - Slightly more prominent glass effect
45
+ - **`secondary`** - Alternative glass styling
46
+ - **`vague`** - Subtle thing
47
+ - **`filled`** - Use for solid container sections (customizable)
48
+
49
+ ---
50
+
51
+ ## Components
52
+
53
+ ### Base Components
54
+
55
+ #### BasePage
56
+
57
+ Root page component with automatic favicon setup, dark background, and decorative background elements.
58
+
59
+ **Props:**
60
+ - `favicon?: string | null` - Custom favicon URL (defaults to BTS theme icon)
61
+ - `showBGDetails?: boolean` - Show/hide decorative background elements (default: `true`)
62
+ - `chainColor?: string` - Color of the animated chain (default: `"#130F15"`)
63
+
64
+ **Example:**
65
+ ```svelte
66
+ <BasePage favicon="/custom-icon.svg">
67
+ <!-- Your app content -->
68
+ </BasePage>
69
+
70
+ <!-- Without background decorations -->
71
+ <BasePage showBGDetails={false}>
72
+ <!-- Clean page without gears/chains -->
73
+ </BasePage>
74
+
75
+ <!-- Custom chain color -->
76
+ <BasePage chainColor="#1a1520">
77
+ <!-- Content with custom chain color -->
78
+ </BasePage>
79
+ ```
80
+
81
+ **Features:**
82
+ - Sets min-height: 100vh
83
+ - Applies #0B070D background
84
+ - Automatically injects BTS favicon unless overridden
85
+ - Resets body/html margins
86
+ - Decorative BGDetails layer with animated gears and swinging chain
87
+
88
+ **Background Details (BGDetails):**
89
+
90
+ The `BGDetails` component renders decorative 1920s-style animated elements:
91
+ - **Chain** - A physics-simulated swinging chain in the top-left corner
92
+ - **Gears** - Rotating interlocked gears in the top-right corner
93
+ - **Single Gear** - A slowly rotating gear in the bottom-left corner
94
+
95
+ These elements are purely decorative (pointer-events: none) and sit behind your content.
96
+ Disable with showBGDetails={false}.
97
+
98
+ ---
99
+
100
+ #### BaseContainer
101
+
102
+ Container with customizable corners and themes.
103
+
104
+ **Props:**
105
+ - `theme?: 'full' | 'primary' | 'secondary' | 'filled'` - Visual theme (default: `'full'`)
106
+ - `padding?: string` - CSS padding value (default: `'1.5rem'`)
107
+ - `borderRadiusTopLeft?: string` - Top-left corner radius (default: `'25px'`)
108
+ - `borderRadiusTopRight?: string` - Top-right corner radius (default: `'25px'`)
109
+ - `borderRadiusBottomLeft?: string` - Bottom-left corner radius (default: `'25px'`)
110
+ - `borderRadiusBottomRight?: string` - Bottom-right corner radius (default: `'25px'`)
111
+
112
+ **Example:**
113
+ ```svelte
114
+ <BaseContainer theme="primary" borderRadiusTopLeft="35px">
115
+ <slot />
116
+ </BaseContainer>
117
+ ```
118
+
119
+ ---
120
+
121
+ #### BaseText
122
+
123
+ Typography component with three text variants.
124
+
125
+ **Props:**
126
+ - `variant: 'title' | 'content' | 'button'` - Text style variant
127
+
128
+ **Variants:**
129
+ - **`title`** - Noto Serif KR 900, 30px - For headings
130
+ - **`content`** - Satoshi 700, 18px - For body text
131
+ - **`button`** - Noto Serif KR 900, 17px - For button labels
132
+
133
+ **Example:**
134
+ ```svelte
135
+ <BaseText variant="title">Page Title</BaseText>
136
+ <BaseText variant="content">This is content text.</BaseText>
137
+ ```
138
+
139
+ ---
140
+
141
+ #### BaseIcon
142
+
143
+ SVG icon wrapper with color variants.
144
+
145
+ **Props:**
146
+ - `svg: string` - SVG markup string
147
+ - `variant?: 'default' | 'toned'` - Color variant (default: `'default'`)
148
+ - `size?: string` - Icon size (default: `'18px'`)
149
+
150
+ **Example:**
151
+ ```svelte
152
+ <script>
153
+ import { BaseIcon, icons } from '@coyalabs/bts-style';
154
+ </script>
155
+
156
+ <BaseIcon svg={icons.folder} variant="toned" size="24px" />
157
+ ```
158
+
159
+ ---
160
+
161
+ ### Structure Components
162
+
163
+ #### TextHeader
164
+
165
+ Header component with title and optional subtitle.
166
+
167
+ **Props:**
168
+ - `title: string` - Main heading text
169
+ - `subtitle?: string` - Optional subheading
170
+
171
+ **Example:**
172
+ ```svelte
173
+ <TextHeader
174
+ title="Welcome"
175
+ subtitle="Get started with BTS Theme"
176
+ />
177
+ ```
178
+
179
+ ---
180
+
181
+ ### Interactive Components
182
+
183
+ #### Button
184
+
185
+ Clickable button extending BaseContainer with icon support.
186
+
187
+ **Props:**
188
+ - `theme?: 'full' | 'primary' | 'secondary' | 'filled'` - Button theme
189
+ - `icon?: string` - Left icon SVG
190
+ - `actionIcon?: string | null` - Right icon SVG (default: arrow, null to hide)
191
+ - `iconRotation?: number` - Left icon rotation in degrees
192
+ - `actionIconRotation?: number` - Right icon rotation in degrees
193
+ - `iconSize?: string` - Left icon size (default: `'18px'`)
194
+ - `actionIconSize?: string` - Right icon size (default: `'18px'`)
195
+ - All BaseContainer corner radius props
196
+
197
+ **Events:**
198
+ - Forwards all events including `on:click`
199
+
200
+ **Example:**
201
+ ```svelte
202
+ <script>
203
+ import { Button, icons } from '@coyalabs/bts-style';
204
+ </script>
205
+
206
+ <Button
207
+ theme="primary"
208
+ icon={icons.folder}
209
+ actionIconRotation={-45}
210
+ on:click={() => console.log('Clicked!')}
211
+ >
212
+ Open Folder
213
+ </Button>
214
+
215
+ <!-- Button without action icon -->
216
+ <Button actionIcon={null} theme="secondary">
217
+ Simple Button
218
+ </Button>
219
+ ```
220
+
221
+ **States:**
222
+ - Hover: Subtle background lightening
223
+ - Active/Pressed: Visual feedback
224
+
225
+ ---
226
+
227
+ #### IconButton
228
+
229
+ Circular icon-only button with hover effects.
230
+
231
+ **Props:**
232
+ - `svg: string` - Icon SVG markup
233
+ - `variant?: 'default' | 'toned'` - Icon color variant
234
+ - `size?: string` - Button size (default: `'20px'`)
235
+
236
+ **Events:**
237
+ - Forwards all events including `on:click`
238
+
239
+ **Example:**
240
+ ```svelte
241
+ <script>
242
+ import { IconButton, icons } from '@coyalabs/bts-style';
243
+ </script>
244
+
245
+ <IconButton
246
+ svg={icons.cross}
247
+ variant="toned"
248
+ on:click={() => closeModal()}
249
+ />
250
+ ```
251
+
252
+ **Effects:**
253
+ - Hover: Scale 1.1, subtle background
254
+ - Active: Scale 0.95
255
+
256
+ ---
257
+
258
+ #### InputBox
259
+
260
+ Text input field with icon support and theme matching.
261
+
262
+ **Props:**
263
+ - `value?: string` - Input value (bindable)
264
+ - `placeholder?: string` - Placeholder text
265
+ - `type?: string` - Input type (default: `'text'`)
266
+ - `theme?: 'full' | 'primary' | 'secondary' | 'filled'` - Visual theme
267
+ - `icon?: string` - Left icon SVG
268
+ - All BaseContainer corner radius props
269
+
270
+ **Example:**
271
+ ```svelte
272
+ <script>
273
+ import { InputBox, icons } from '@coyalabs/bts-style';
274
+ let username = '';
275
+ </script>
276
+
277
+ <InputBox
278
+ bind:value={username}
279
+ placeholder="Enter username..."
280
+ icon={icons.pen}
281
+ theme="primary"
282
+ />
283
+ ```
284
+
285
+
286
+ ---
287
+
288
+ #### Toggle
289
+
290
+ Animated toggle switch with on/off states.
291
+
292
+ **Props:**
293
+ - `checked?: boolean` - Toggle state (bindable)
294
+
295
+ **Example:**
296
+ ```svelte
297
+ <script>
298
+ import { Toggle } from '@coyalabs/bts-style';
299
+ let enabled = false;
300
+ </script>
301
+
302
+ <Toggle bind:checked={enabled} />
303
+ <p>State: {enabled ? 'On' : 'Off'}</p>
304
+ ```
305
+ ---
306
+
307
+ #### Tooltip
308
+
309
+ Hover tooltip that displays above or below an icon.
310
+
311
+ **Props:**
312
+ - `icon: string` - Icon SVG markup
313
+ - `text: string` - Tooltip text content
314
+ - `iconSize?: string` - Icon size (default: `'18px'`)
315
+
316
+ **Example:**
317
+ ```svelte
318
+ <script>
319
+ import { Tooltip, icons } from '@coyalabs/bts-style';
320
+ </script>
321
+
322
+ <Tooltip
323
+ icon={icons.folder}
324
+ text="This is a helpful explanation"
325
+ iconSize="20px"
326
+ />
327
+ ```
328
+
329
+ **Features:**
330
+ - Automatic positioning to fit on screen
331
+ - Min width 150px, max width 300px
332
+
333
+ ---
334
+
335
+ #### TabBar
336
+
337
+ Vertical tab navigation with support for categorized groups.
338
+
339
+ **Props:**
340
+ - `tabs: Array<TabItem>` - Array of tabs and separators
341
+ - `activeTab: string` - Currently active tab ID (bindable)
342
+ - `onTabChange?: (tabId: string) => void` - Callback when tab changes
343
+
344
+ **TabItem Type:**
345
+ ```typescript
346
+ type TabItem = {
347
+ id?: string; // Required for tabs, omit for separators
348
+ label: string; // Tab/separator text
349
+ icon?: string; // Optional icon SVG
350
+ type?: 'tab' | 'separator'; // Default: 'tab'
351
+ }
352
+ ```
353
+
354
+ **Example:**
355
+ ```svelte
356
+ <script>
357
+ import { TabBar, icons } from '@coyalabs/bts-style';
358
+
359
+ let currentTab = 'home';
360
+
361
+ const tabs = [
362
+ { type: 'separator', label: 'Navigation' },
363
+ { id: 'home', label: 'Home', icon: icons.folder },
364
+ { id: 'about', label: 'About' },
365
+ { type: 'separator', label: 'Account' },
366
+ { id: 'settings', label: 'Settings' },
367
+ { id: 'profile', label: 'Profile' }
368
+ ];
369
+ </script>
370
+
371
+ <TabBar
372
+ {tabs}
373
+ bind:activeTab={currentTab}
374
+ onTabChange={(id) => console.log('Tab:', id)}
375
+ />
376
+ ```
377
+
378
+ **Features:**
379
+ - Vertical layout, 175px fixed width
380
+ - Active tab uses `primary` theme, inactive uses `secondary`
381
+ - Adaptive corner radius: 25px at group boundaries, 18px for middle tabs
382
+ - Text separators for grouping tabs into categories
383
+ - Categories have 1rem spacing between them
384
+ - Buttons within categories have 4px spacing
385
+
386
+ **Corner Radius Behavior:**
387
+ - First tab in a group: top corners 25px
388
+ - Last tab in a group: bottom corners 25px
389
+ - Middle tabs: all corners 18px
390
+ - Separators create group boundaries
391
+
392
+ ---
393
+
394
+ #### TreeDirectory
395
+
396
+ Expandable file/folder tree with recursive structure.
397
+
398
+ **Props:**
399
+ - `items: Array<TreeItem>` - Tree data structure
400
+ - `showCount?: boolean` - Show item counts in folders (default: `false`)
401
+ - `itemIcon?: string` - Custom icon for items
402
+ - `topFoldersExpanded?: boolean` - Expand top-level folders initially (default: `false`)
403
+ - `draggable?: boolean` - Enable drag and drop functionality (default: `false`)
404
+ - `currentPath?: string` - Current folder path for nested items (default: `''`)
405
+ - `level?: number` - Internal: Current nesting level (default: `0`)
406
+
407
+ **TreeItem Type:**
408
+ ```typescript
409
+ type TreeItem = {
410
+ name: string;
411
+ type: 'file' | 'folder';
412
+ children?: TreeItem[];
413
+ data?: any; // Custom data attached to item
414
+ variant?: 'full' | 'primary' | 'secondary' | 'filled' | 'special-filled'; // Theme variant
415
+ suffixIcon?: string; // SVG icon displayed on the right
416
+ }
417
+ ```
418
+
419
+ **Events:**
420
+ - `on:itemClick` - Fired when any item is clicked
421
+ - `event.detail.item` - The clicked item object
422
+ - `event.detail.type` - Either `'file'` or `'folder'`
423
+ - `on:rightClick` - Fired when any item is right-clicked
424
+ - `event.detail.item` - The right-clicked item object
425
+ - `event.detail.type` - Either `'file'` or `'folder'`
426
+ - `event.detail.event` - The original mouse event (for positioning context menus)
427
+ - `on:dragStart` - Fired when dragging a file starts (requires `draggable={true}`)
428
+ - `event.detail.item` - The dragged item object
429
+ - `event.detail.sourcePath` - Path of the source folder
430
+ - `on:itemDrop` - Fired when a file is dropped (requires `draggable={true}`)
431
+ - `event.detail.item` - The dropped item data
432
+ - `event.detail.sourcePath` - Original folder path
433
+ - `event.detail.targetPath` - Destination folder path
434
+
435
+ **Example:**
436
+ ```svelte
437
+ <script>
438
+ import { TreeDirectory, icons } from '@coyalabs/bts-style';
439
+
440
+ const fileTree = [
441
+ {
442
+ name: 'src',
443
+ type: 'folder',
444
+ variant: 'primary',
445
+ children: [
446
+ {
447
+ name: 'App.svelte',
448
+ type: 'file',
449
+ variant: 'secondary',
450
+ suffixIcon: icons.pen
451
+ },
452
+ { name: 'main.js', type: 'file' }
453
+ ]
454
+ },
455
+ {
456
+ name: 'README.md',
457
+ type: 'file',
458
+ suffixIcon: '<svg>...</svg>'
459
+ }
460
+ ];
461
+
462
+ function handleItemClick(event) {
463
+ const { item, type } = event.detail;
464
+ console.log(`Clicked ${type}:`, item.name);
465
+ }
466
+
467
+ function handleRightClick(event) {
468
+ const { item, type, event: mouseEvent } = event.detail;
469
+ console.log(`Right-clicked ${type}:`, item.name);
470
+ // Use mouseEvent.clientX and mouseEvent.clientY for positioning context menus
471
+ }
472
+
473
+ function handleDrop(event) {
474
+ const { item, sourcePath, targetPath } = event.detail;
475
+ console.log(`Moved ${item.name} from ${sourcePath} to ${targetPath}`);
476
+ }
477
+ </script>
478
+
479
+ <TreeDirectory
480
+ items={fileTree}
481
+ showCount={true}
482
+ topFoldersExpanded={true}
483
+ draggable={true}
484
+ on:itemClick={handleItemClick}
485
+ on:rightClick={handleRightClick}
486
+ on:itemDrop={handleDrop}
487
+ />
488
+ ```
489
+
490
+ **Methods:**
491
+ ```svelte
492
+ <script>
493
+ let tree;
494
+
495
+ // Get current state
496
+ const state = tree.getState();
497
+
498
+ // Restore state
499
+ tree.setState(state);
500
+
501
+ // Expand all folders
502
+ tree.expandAll();
503
+
504
+ // Collapse all folders
505
+ tree.collapseAll();
506
+ </script>
507
+
508
+ <TreeDirectory bind:this={tree} items={fileTree} />
509
+ ```
510
+
511
+ **Features:**
512
+ - Slide animations (150ms, skipped on initial render)
513
+ - Recursive item counting
514
+ - State persistence
515
+ - Event forwarding for click handling
516
+ - Initial expansion option for top-level folders
517
+ - Adaptive corner radius based on nesting
518
+ - Padding increases with depth
519
+ - Per-item theme variants (override default folder/file themes)
520
+ - Suffix icon support for displaying icons on the right side
521
+ - Optional drag and drop functionality for files
522
+ - Visual feedback during drag operations (folder highlight)
523
+ - Path tracking for nested folder structures
524
+
525
+ **Drag and Drop:**
526
+
527
+ When `draggable={true}`:
528
+ - Only files can be dragged (folders are drop targets)
529
+ - Dragged files show reduced opacity
530
+ - Folders highlight when dragged over
531
+ - Drop on folders to move files into them
532
+ - Drop on empty space to move to current level
533
+ - `on:itemDrop` event provides source and target paths for handling moves
534
+
535
+ **Customization:**
536
+
537
+ **Item Variants:**
538
+ Each item can have a custom `variant` to override the default theme:
539
+ - Folders default to `'primary'`
540
+ - Files default to `'secondary'`
541
+ - Set `variant` on any item to use a different theme
542
+
543
+ **Suffix Icons:**
544
+ Display additional icons on the right side of items:
545
+ ```svelte
546
+ {
547
+ name: 'config.json',
548
+ type: 'file',
549
+ suffixIcon: '<svg>...</svg>' // Any SVG string
550
+ }
551
+ ```
552
+
553
+ ---
554
+
555
+ ### Popup System
556
+
557
+ #### Popup
558
+
559
+ Global modal popup overlay (singleton).
560
+
561
+ **Usage:**
562
+ ```svelte
563
+ <script>
564
+ import { Popup, popupStore } from '@coyalabs/bts-style';
565
+ </script>
566
+
567
+ <!-- Place once at app root -->
568
+ <Popup />
569
+ ```
570
+
571
+ **Features:**
572
+ - Fade overlay (250ms)
573
+ - Fly dialog animation (300ms, backOut easing)
574
+ - Close button with toned icon
575
+ - ESC key support (built-in)
576
+
577
+ ---
578
+
579
+ #### popupStore
580
+
581
+ Writable store for controlling the popup.
582
+
583
+ **Methods:**
584
+
585
+ ##### open()
586
+ ```typescript
587
+ popupStore.open(
588
+ title: string,
589
+ component: SvelteComponent,
590
+ props?: object,
591
+ subtitle?: string
592
+ )
593
+ ```
594
+
595
+ Opens popup with custom component.
596
+
597
+ **Example:**
598
+ ```svelte
599
+ <script>
600
+ import { popupStore } from '@coyalabs/bts-style';
601
+ import MyCustomPopup from './MyCustomPopup.svelte';
602
+ </script>
603
+
604
+ <button on:click={() =>
605
+ popupStore.open(
606
+ 'Settings',
607
+ MyCustomPopup,
608
+ { userId: 123 },
609
+ 'Configure your preferences'
610
+ )
611
+ }>
612
+ Open Settings
613
+ </button>
614
+ ```
615
+
616
+ ##### confirm()
617
+ ```typescript
618
+ popupStore.confirm(
619
+ title: string,
620
+ message: string,
621
+ options?: {
622
+ onConfirm?: () => void,
623
+ onCancel?: () => void,
624
+ confirmText?: string,
625
+ cancelText?: string
626
+ }
627
+ )
628
+ ```
629
+
630
+ Shows confirmation dialog.
631
+
632
+ **Example:**
633
+ ```svelte
634
+ <button on:click={() =>
635
+ popupStore.confirm(
636
+ 'Delete Item',
637
+ 'Are you sure? This cannot be undone.',
638
+ {
639
+ onConfirm: () => deleteItem(),
640
+ onCancel: () => console.log('Cancelled'),
641
+ confirmText: 'Delete',
642
+ cancelText: 'Keep'
643
+ }
644
+ )
645
+ }>
646
+ Delete
647
+ </button>
648
+ ```
649
+
650
+ ##### alert()
651
+ ```typescript
652
+ popupStore.alert(
653
+ title: string,
654
+ message: string,
655
+ options?: {
656
+ onOk?: () => void,
657
+ okText?: string
658
+ }
659
+ )
660
+ ```
661
+
662
+ Shows alert dialog.
663
+
664
+ **Example:**
665
+ ```svelte
666
+ popupStore.alert(
667
+ 'Success',
668
+ 'Your changes have been saved!',
669
+ {
670
+ onOk: () => navigateToHome(),
671
+ okText: 'Got it'
672
+ }
673
+ );
674
+ ```
675
+
676
+ ##### prompt()
677
+ ```typescript
678
+ popupStore.prompt(
679
+ title: string,
680
+ message: string,
681
+ options?: {
682
+ onSubmit?: (value: string) => void,
683
+ onCancel?: () => void,
684
+ placeholder?: string,
685
+ submitText?: string,
686
+ cancelText?: string
687
+ }
688
+ )
689
+ ```
690
+
691
+ Shows input prompt dialog.
692
+
693
+ **Example:**
694
+ ```svelte
695
+ popupStore.prompt(
696
+ 'Enter Name',
697
+ 'Please provide your display name:',
698
+ {
699
+ onSubmit: (name) => updateProfile(name),
700
+ placeholder: 'Your name...',
701
+ submitText: 'Save',
702
+ cancelText: 'Skip'
703
+ }
704
+ );
705
+ ```
706
+
707
+ ##### close()
708
+ ```typescript
709
+ popupStore.close()
710
+ ```
711
+
712
+ Closes the current popup.
713
+
714
+ ---
715
+
716
+ #### Popup Presets
717
+
718
+ The popup system includes three pre-built popup components that can be triggered via `popupStore` methods.
719
+
720
+ ##### ConfirmPopup
721
+
722
+ A two-button confirmation dialog with confirm and cancel actions.
723
+
724
+ **Features:**
725
+ - Primary theme confirm button (left)
726
+ - Secondary theme cancel button (right)
727
+ - Callbacks: `onConfirm`, `onCancel`
728
+ - Customizable button text
729
+
730
+ **Triggered via:**
731
+ ```svelte
732
+ popupStore.confirm(title, message, options)
733
+ ```
734
+
735
+ **Visual Layout:**
736
+ - Message text displayed as subtitle
737
+ - Two buttons side-by-side
738
+ - Confirm button uses primary theme
739
+ - Cancel button uses secondary theme
740
+
741
+ ---
742
+
743
+ ##### AlertPopup
744
+
745
+ A single-button alert dialog for notifications.
746
+
747
+ **Features:**
748
+ - Single OK button with primary theme
749
+ - Callback: `onOk`
750
+ - Customizable button text
751
+ - Auto-closes on OK click
752
+
753
+ **Triggered via:**
754
+ ```svelte
755
+ popupStore.alert(title, message, options)
756
+ ```
757
+
758
+ **Visual Layout:**
759
+ - Message text displayed as subtitle
760
+ - Single centered OK button
761
+ - Primary theme button
762
+
763
+ ---
764
+
765
+ ##### PromptPopup
766
+
767
+ An input dialog that prompts the user for text input.
768
+
769
+ **Features:**
770
+ - InputBox component for text entry
771
+ - Submit button (primary theme)
772
+ - Cancel button (secondary theme)
773
+ - Callbacks: `onSubmit(value)`, `onCancel`
774
+ - Customizable placeholder and button text
775
+
776
+ **Triggered via:**
777
+ ```svelte
778
+ popupStore.prompt(title, message, options)
779
+ ```
780
+
781
+ **Visual Layout:**
782
+ - Message text displayed as subtitle
783
+ - InputBox with customizable placeholder
784
+ - Two buttons: Submit (primary) and Cancel (secondary)
785
+ - Submit returns the input value to callback
786
+
787
+ **Example with all options:**
788
+ ```svelte
789
+ popupStore.prompt(
790
+ 'Rename File',
791
+ 'Enter a new name for this file:',
792
+ {
793
+ placeholder: 'filename.txt',
794
+ submitText: 'Rename',
795
+ cancelText: 'Cancel',
796
+ onSubmit: (newName) => {
797
+ console.log('New name:', newName);
798
+ renameFile(newName);
799
+ },
800
+ onCancel: () => console.log('Rename cancelled')
801
+ }
802
+ );
803
+ ```
804
+
805
+ ---
806
+
807
+ ### Toast System
808
+
809
+ #### Toast
810
+
811
+ Global toast notification container (singleton).
812
+
813
+ **Usage:**
814
+ ```svelte
815
+ <script>
816
+ import { Toast, toastStore } from '@coyalabs/bts-style';
817
+ </script>
818
+
819
+ <!-- Place once at app root -->
820
+ <Toast />
821
+ ```
822
+
823
+ **Features:**
824
+ - Bottom-right stacking
825
+ - Smooth slide animations (300ms in, 200ms out)
826
+ - Auto-dismiss with configurable duration
827
+ - Manual dismiss via close button
828
+ - Non-blocking, less intrusive than popups
829
+
830
+ ---
831
+
832
+ #### toastStore
833
+
834
+ Writable store for controlling toast notifications.
835
+
836
+ **Methods:**
837
+
838
+ ##### show()
839
+ ```typescript
840
+ toastStore.show(
841
+ message: string,
842
+ duration?: number // Default: 4000ms, 0 = no auto-dismiss
843
+ ): string // Returns toast ID
844
+ ```
845
+
846
+ Shows a toast notification.
847
+
848
+ **Example:**
849
+ ```svelte
850
+ <script>
851
+ import { toastStore } from '@coyalabs/bts-style';
852
+ </script>
853
+
854
+ <button on:click={() => toastStore.show('File saved successfully!')}>
855
+ Save
856
+ </button>
857
+
858
+ <!-- Custom duration -->
859
+ <button on:click={() => toastStore.show('Processing...', 2000)}>
860
+ Process
861
+ </button>
862
+
863
+ <!-- No auto-dismiss -->
864
+ <button on:click={() => toastStore.show('Important message', 0)}>
865
+ Important
866
+ </button>
867
+ ```
868
+
869
+ ##### dismiss()
870
+ ```typescript
871
+ toastStore.dismiss(id: string)
872
+ ```
873
+
874
+ Dismisses a specific toast by ID.
875
+
876
+ **Example:**
877
+ ```svelte
878
+ <script>
879
+ const toastId = toastStore.show('Click to dismiss', 0);
880
+ </script>
881
+
882
+ <button on:click={() => toastStore.dismiss(toastId)}>
883
+ Dismiss Toast
884
+ </button>
885
+ ```
886
+
887
+ ##### dismissAll()
888
+ ```typescript
889
+ toastStore.dismissAll()
890
+ ```
891
+
892
+ Dismisses all active toasts.
893
+
894
+ **Example:**
895
+ ```svelte
896
+ <button on:click={() => toastStore.dismissAll()}>
897
+ Clear All Toasts
898
+ </button>
899
+ ```
900
+
901
+ **Visual Design:**
902
+ - Uses Button component with secondary theme
903
+ - Help icon on the left (info indicator)
904
+ - Close icon (crossb) on the right
905
+ - Stacks vertically with 0.75rem gap
906
+ - Slides in from right, slides out to right
907
+ - Fixed position at bottom-right (2rem from edges)
908
+ - Z-index 10000 (above popups)
909
+
910
+ **Best Practices:**
911
+
912
+ Place `<Toast />` once at your app root alongside `<Popup />`:
913
+
914
+ ```svelte
915
+ <!-- App.svelte -->
916
+ <script>
917
+ import { BasePage, Popup, Toast } from '@coyalabs/bts-style';
918
+ </script>
919
+
920
+ <BasePage>
921
+ <!-- App content -->
922
+ </BasePage>
923
+
924
+ <Popup />
925
+ <Toast />
926
+ ```
927
+
928
+ ---
929
+
930
+ ### Special Components
931
+
932
+ Glowy components with unique styling and animations.
933
+
934
+ #### SpecialAction
935
+
936
+ A special-themed button with gradient background and optional tooltip.
937
+
938
+ **Props:**
939
+ - `label: string` - Button text
940
+ - `tooltipText?: string` - Optional tooltip text displayed on the right
941
+
942
+ **Example:**
943
+ ```svelte
944
+ <script>
945
+ import { SpecialAction } from '@coyalabs/bts-style';
946
+ </script>
947
+
948
+ <SpecialAction
949
+ label="AI Generate"
950
+ tooltipText="Uses AI to generate content"
951
+ />
952
+ ```
953
+
954
+ **Features:**
955
+ - Purple gradient background (`special-filled` theme)
956
+ - AI icon on the left
957
+ - Tooltip positioned at far right (when provided)
958
+ - Enhanced hover effect with brighter gradient
959
+ - Pressed state with darker gradient
960
+
961
+ **For?**
962
+ - AI actions.
963
+
964
+ **Styling:**
965
+ - Background: Linear gradient purple tones
966
+ - Enhanced glow effects on hover
967
+ - User-select disabled for better UX
968
+
969
+ ---
970
+
971
+ #### SpecialParagraph
972
+
973
+ Animated text component that reveals words sequentially with fade and blur effects.
974
+
975
+ **Props:**
976
+ - `text: string` - The text content to animate
977
+ - `wordDelay?: number` - Delay between each word appearing in ms (default: `50`)
978
+ - `startDelay?: number` - Initial delay before animation starts in ms (default: `0`)
979
+ - `animationDuration?: number` - Animation duration for each word in ms (default: `300`)
980
+ - `variant?: 'title' | 'content' | 'button'` - Text styling variant (default: `'content'`)
981
+ - `textModifier?: string` - Font size adjustment (default: `'0px'`)
982
+ - `autoPlay?: boolean` - Start animation automatically on mount (default: `true`)
983
+
984
+ **Methods:**
985
+ - `play()` - Start/restart the animation
986
+ - `reset()` - Reset to hidden state
987
+ - `showAll()` - Show all words immediately
988
+
989
+ **Example:**
990
+ ```svelte
991
+ <script>
992
+ import { SpecialParagraph } from '@coyalabs/bts-style';
993
+ let paragraph;
994
+ </script>
995
+
996
+ <!-- Auto-playing paragraph -->
997
+ <SpecialParagraph
998
+ text="This text will animate in word by word with smooth effects"
999
+ wordDelay={80}
1000
+ variant="content"
1001
+ />
1002
+
1003
+ <!-- Manual control -->
1004
+ <SpecialParagraph
1005
+ bind:this={paragraph}
1006
+ text="Click the button to animate!"
1007
+ autoPlay={false}
1008
+ />
1009
+ <button on:click={() => paragraph.play()}>Play Animation</button>
1010
+ ```
1011
+
1012
+ **Animation Effects:**
1013
+ - Each word fades in from opacity 0 to 1
1014
+ - Slides up from 8px translateY offset
1015
+ - Blur transitions from 4px to 0
1016
+ - Smooth easing transitions
1017
+
1018
+ **For?**
1019
+ - Fancier AI.
1020
+
1021
+ **Use Cases:**
1022
+ - Intro text animations
1023
+ - Loading state messages
1024
+ - Drawing attention to important content
1025
+ - Storytelling and narrative interfaces
1026
+
1027
+ ---
1028
+
1029
+ #### ContextMenu
1030
+
1031
+ Categorized menu component with separator support, similar to TabBar layout.
1032
+
1033
+ **Props:**
1034
+ - `items: Array<ContextMenuItem>` - Array of menu items and separators
1035
+ - `selectedValue?: any` - Currently selected item value
1036
+ - `onSelect?: (value: any) => void` - Callback when item is selected
1037
+
1038
+ **ContextMenuItem Type:**
1039
+ ```typescript
1040
+ type ContextMenuItem = {
1041
+ label: string;
1042
+ value?: any; // Required for items, omit for separators
1043
+ disabled?: boolean;
1044
+ type?: 'item' | 'separator'; // Default: 'item'
1045
+ }
1046
+ ```
1047
+
1048
+ **Example:**
1049
+ ```svelte
1050
+ <script>
1051
+ import { ContextMenu } from '@coyalabs/bts-style';
1052
+
1053
+ let selectedValue = 'cut';
1054
+
1055
+ const menuItems = [
1056
+ { label: 'Edit', type: 'separator' },
1057
+ { label: 'Cut', value: 'cut' },
1058
+ { label: 'Copy', value: 'copy' },
1059
+ { label: 'Paste', value: 'paste', disabled: true },
1060
+ { label: 'View', type: 'separator' },
1061
+ { label: 'Zoom In', value: 'zoomIn' },
1062
+ { label: 'Zoom Out', value: 'zoomOut' }
1063
+ ];
1064
+ </script>
1065
+
1066
+ <ContextMenu
1067
+ items={menuItems}
1068
+ {selectedValue}
1069
+ onSelect={(val) => handleAction(val)}
1070
+ />
1071
+ ```
1072
+
1073
+ **Features:**
1074
+ - Category grouping with separator labels
1075
+ - Selected item highlighting
1076
+ - Disabled item support with reduced opacity
1077
+ - Hover effects on enabled items
1078
+ - Filled theme container
1079
+ - Automatic category spacing and borders
1080
+ - Text ellipsis for long labels
1081
+
1082
+ **Visual Layout:**
1083
+ - Categories separated by labeled dividers
1084
+ - First category has no top border
1085
+ - Subsequent categories have subtle top border
1086
+ - 0.5rem padding around separators
1087
+ - 4px spacing between items
1088
+
1089
+ ---
1090
+
1091
+ #### Dropdown
1092
+
1093
+ Select dropdown with collapsible options menu.
1094
+
1095
+ **Props:**
1096
+ - `label: string` - Default button text before selection
1097
+ - `icon?: string` - Optional left icon SVG
1098
+ - `theme?: 'full' | 'primary' | 'secondary'` - Button theme (default: `'full'`)
1099
+ - `width?: string` - Fixed width for dropdown (default: `'200px'`)
1100
+ - `options: Array<DropdownOption>` - Array of selectable options
1101
+ - `value?: any` - Currently selected value (bindable)
1102
+ - `onChange?: (value: any) => void` - Callback when selection changes
1103
+ - All BaseContainer corner radius props
1104
+
1105
+ **DropdownOption Type:**
1106
+ ```typescript
1107
+ type DropdownOption = {
1108
+ label: string;
1109
+ value: any;
1110
+ disabled?: boolean;
1111
+ type?: 'item' | 'separator'; // Optional: use for category separation
1112
+ }
1113
+ ```
1114
+
1115
+ **Example:**
1116
+ ```svelte
1117
+ <script>
1118
+ import { Dropdown, icons } from '@coyalabs/bts-style';
1119
+
1120
+ let selectedValue = 'option1';
1121
+
1122
+ const options = [
1123
+ { label: 'Basic', type: 'separator' },
1124
+ { label: 'Option 1', value: 'option1' },
1125
+ { label: 'Option 2', value: 'option2' },
1126
+ { label: 'Advanced', type: 'separator' },
1127
+ { label: 'Option 3', value: 'option3' },
1128
+ { label: 'Disabled', value: 'option4', disabled: true }
1129
+ ];
1130
+ </script>
1131
+
1132
+ <Dropdown
1133
+ label="Select an option"
1134
+ icon={icons.folder}
1135
+ theme="primary"
1136
+ width="250px"
1137
+ {options}
1138
+ bind:value={selectedValue}
1139
+ onChange={(val) => console.log('Selected:', val)}
1140
+ />
1141
+ ```
1142
+
1143
+ **Features:**
1144
+ - Fixed width with text truncation (ellipsis)
1145
+ - Expand icon rotates 180° when open
1146
+ - Slide animation for menu (150ms)
1147
+ - Click outside to close
1148
+ - Uses ContextMenu component internally
1149
+ - Support for category separators
1150
+ - Selected item highlighted
1151
+ - Disabled items shown with reduced opacity
1152
+
1153
+ ---
1154
+
1155
+ #### LinearList
1156
+
1157
+ Vertical list component with customizable actions for each item.
1158
+
1159
+ **Props:**
1160
+ - `items: Array<ListItem>` - Array of list items
1161
+
1162
+ **ListItem Type:**
1163
+ ```typescript
1164
+ type CustomAction = {
1165
+ label: string;
1166
+ actionIcon?: string;
1167
+ }
1168
+
1169
+ type ListItem = {
1170
+ data?: any; // Custom data attached to item
1171
+ customActions?: CustomAction[];
1172
+ removeButton?: boolean;
1173
+ }
1174
+ ```
1175
+
1176
+ **Events:**
1177
+ - `on:action` - Fired when any custom action is clicked
1178
+ - `event.detail.index` - Item index
1179
+ - `event.detail.actionLabel` - Action label that was clicked
1180
+ - `event.detail.item` - The item object
1181
+ - `on:remove` - Fired when remove button is clicked
1182
+ - `event.detail.index` - Item index
1183
+ - `event.detail.item` - The item object
1184
+
1185
+ **Example:**
1186
+ ```svelte
1187
+ <script>
1188
+ import { LinearList, icons } from '@coyalabs/bts-style';
1189
+
1190
+ const items = [
1191
+ {
1192
+ data: { id: 1, name: 'First Item' },
1193
+ customActions: [
1194
+ { label: 'Edit', actionIcon: icons.pen },
1195
+ { label: 'View' }
1196
+ ],
1197
+ removeButton: true
1198
+ },
1199
+ {
1200
+ data: { id: 2, name: 'Second Item' },
1201
+ customActions: [
1202
+ { label: 'Download' }
1203
+ ],
1204
+ removeButton: true
1205
+ }
1206
+ ];
1207
+
1208
+ function handleAction(event) {
1209
+ const { index, actionLabel, item } = event.detail;
1210
+ console.log(`${actionLabel} clicked on item ${index}`, item);
1211
+ }
1212
+
1213
+ function handleRemove(event) {
1214
+ const { index, item } = event.detail;
1215
+ console.log(`Remove item ${index}`, item);
1216
+ }
1217
+ </script>
1218
+
1219
+ <LinearList
1220
+ {items}
1221
+ on:action={handleAction}
1222
+ on:remove={handleRemove}
1223
+ >
1224
+ {#snippet children({ item, index })}
1225
+ <div>{item.data.name}</div>
1226
+ {/snippet}
1227
+ </LinearList>
1228
+ ```
1229
+
1230
+ **Features:**
1231
+ - Left-aligned content slot with `item` and `index` props
1232
+ - Right-aligned action buttons (horizontal)
1233
+ - Optional remove button (icon-only, toned variant)
1234
+ - 1px bottom border separator (rgba(161, 143, 143, 0.24))
1235
+ - No border on last item
1236
+ - 10px vertical padding per item
1237
+ - No horizontal padding
1238
+ - No spacing between items
1239
+ - Event-based action handling
1240
+
1241
+ **Visual Layout:**
1242
+ - Each item is a flex row with space-between
1243
+ - Content on the left, actions on the right
1244
+ - Actions have 0.5rem gap between them
1245
+ - Remove button appears at the end of actions
1246
+ - Borders are internal strokes (bottom edge only)
1247
+
1248
+ ---
1249
+
1250
+ #### Separator
1251
+
1252
+ Decorative SVG separator with tiled middle section.
1253
+
1254
+ **Props:**
1255
+ - `height?: string` - Separator height (default: `'12px'`)
1256
+ - `width?: string` - Separator width (default: `'100%'`)
1257
+ - `margin?: string` - CSS margin (default: `'2rem 0'`)
1258
+
1259
+ **Example:**
1260
+ ```svelte
1261
+ <script>
1262
+ import { Separator } from '@coyalabs/bts-style';
1263
+ </script>
1264
+
1265
+ <Separator />
1266
+ <Separator height="20px" margin="3rem 0" />
1267
+ ```
1268
+
1269
+ **Features:**
1270
+ - Three-part design: left piece, tiled middle, right piece
1271
+ - Inline SVG data URLs for performance
1272
+ - Scales to container width
1273
+ - Elegant visual break between sections
1274
+
1275
+ ---
1276
+
1277
+ ### Icons
1278
+
1279
+ The package exports a collection of built-in SVG icons.
1280
+
1281
+ **Usage:**
1282
+ ```svelte
1283
+ <script>
1284
+ import { icons, BaseIcon } from '@coyalabs/bts-style';
1285
+ </script>
1286
+
1287
+ <BaseIcon svg={icons.arrow} />
1288
+ <BaseIcon svg={icons.folder} />
1289
+ <BaseIcon svg={icons.icon_expand} />
1290
+ <BaseIcon svg={icons.cross} />
1291
+ <BaseIcon svg={icons.pen} />
1292
+ ```
1293
+
1294
+ **Available Icons:**
1295
+ - `arrow` - Right arrow navigation
1296
+ - `folder` - Folder icon
1297
+ - `icon_expand` - Expand/collapse chevron
1298
+ - `cross` - Close/dismiss X
1299
+ - `pen` - Edit/write pen
1300
+
1301
+ **Custom Icons:**
1302
+
1303
+ You can use any SVG string with icon-supporting components:
1304
+
1305
+ ```svelte
1306
+ <script>
1307
+ const myIcon = '<svg>...</svg>';
1308
+ </script>
1309
+
1310
+ <Button icon={myIcon}>Custom Icon</Button>
1311
+ <BaseIcon svg={myIcon} />
1312
+ ```
1313
+
1314
+ ---
1315
+
1316
+ ## Styling
1317
+
1318
+ ### Corner Radius Customization
1319
+
1320
+ All components extending BaseContainer support individual corner radius props:
1321
+
1322
+ ```svelte
1323
+ <Button
1324
+ borderRadiusTopLeft="35px"
1325
+ borderRadiusTopRight="35px"
1326
+ borderRadiusBottomLeft="15px"
1327
+ borderRadiusBottomRight="15px"
1328
+ theme="primary"
1329
+ >
1330
+ Asymmetric Button
1331
+ </Button>
1332
+ ```
1333
+
1334
+ ### Theme Customization
1335
+
1336
+ You can customize filled theme backgrounds by targeting CSS variables or extending components.
1337
+
1338
+ ---
1339
+
1340
+ ## Best Practices
1341
+
1342
+ ### Layout
1343
+
1344
+ ```svelte
1345
+ <BasePage>
1346
+ <main style="max-width: 900px; margin: 0 auto; padding: 3rem 2rem;">
1347
+ <TextHeader title="My App" subtitle="Welcome" />
1348
+
1349
+ <!-- Your content -->
1350
+ </main>
1351
+ </BasePage>
1352
+ ```
1353
+
1354
+ ### Popup Management
1355
+
1356
+ Place `<Popup />` once at your app root:
1357
+
1358
+ ```svelte
1359
+ <!-- App.svelte -->
1360
+ <script>
1361
+ import { BasePage, Popup } from '@coyalabs/bts-style';
1362
+ </script>
1363
+
1364
+ <BasePage>
1365
+ <!-- App content -->
1366
+ </BasePage>
1367
+
1368
+ <Popup />
1369
+ ```
1370
+
1371
+ ### Icons
1372
+
1373
+ For consistent styling, prefer using `BaseIcon` over raw SVG:
1374
+
1375
+ ```svelte
1376
+ <!-- Good -->
1377
+ <BaseIcon svg={myIcon} variant="toned" />
1378
+
1379
+ <!-- Less ideal -->
1380
+ {@html myIcon}
1381
+ ```
1382
+
1383
+ ---
1384
+
1385
+ ## Development
1386
+
1387
+ ### Local Development
1388
+
1389
+ Link the package locally for testing:
1390
+
1391
+ ```bash
1392
+ # In the package directory
1393
+ cd @bts-theme/bts-theme
1394
+ npm run package
1395
+ npm link
1396
+
1397
+ # In your project
1398
+ npm link @coyalabs/bts-style
1399
+ ```
1400
+
1401
+ After making changes:
1402
+
1403
+ ```bash
1404
+ npm run package
1405
+ ```
1406
+
1407
+ **Note:** You may need to clear Vite cache after rebuilding:
1408
+ ```bash
1409
+ rm -rf node_modules/.vite
1410
+ ```
1411
+
1412
+ ### Publishing
1413
+
1414
+ ```bash
1415
+ npm run release # Bumps version, packages, and publishes
1416
+ ```
1417
+
1418
+ ---
1419
+
1420
+ ## TypeScript Support
1421
+
1422
+ All components include TypeScript definitions. Import types as needed:
1423
+
1424
+ ```typescript
1425
+ import type { TreeItem } from '@coyalabs/bts-style';
1426
+ ```
1427
+
1428
+ ---
1429
+
1430
+ ## Package Structure
1431
+
1432
+ ```
1433
+ @coyalabs/bts-style/
1434
+ ├── dist/ # Compiled package
1435
+ ├── public/ # Static assets
1436
+ │ ├── favicon.svg # Default BTS favicon
1437
+ │ └── PLACE_YOUR_IMAGES_HERE.txt
1438
+ ├── src/
1439
+ │ ├── Base/ # Base components
1440
+ │ ├── Components/ # Interactive components
1441
+ │ ├── Structure/ # Layout components
1442
+ │ ├── icons.js # Icon definitions
1443
+ │ └── index.ts # Main export
1444
+ └── package.json
1445
+ ```
1446
+
1447
+ ---
1448
+
1449
+ ## License
1450
+
1451
+ MIT
1452
+
1453
+ ---
1454
+
1455
+ ## Repository
1456
+
1457
+ [github.com/sparklescoya/svelte-bts-theme](https://github.com/sparklescoya/svelte-bts-theme)
1458
+
1459
+ ---
1460
+
1461
+ ## Credits
1462
+
1463
+ Created with ❤️ using Svelte 5
1464
+
1465
+ Fonts: [Google Fonts (Noto Serif KR)](https://fonts.google.com/), [Fontshare (Satoshi)](https://www.fontshare.com/)