soltana-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +158 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +7 -0
- package/dist/config/register.d.ts +27 -0
- package/dist/config/stylesheet.d.ts +13 -0
- package/dist/config/types.d.ts +177 -0
- package/dist/config/types.js +7 -0
- package/dist/config/validation.d.ts +29 -0
- package/dist/config/validation.js +59 -0
- package/dist/enhancers/accordion.d.ts +19 -0
- package/dist/enhancers/carousel.d.ts +21 -0
- package/dist/enhancers/collapsible.d.ts +14 -0
- package/dist/enhancers/color-picker.d.ts +20 -0
- package/dist/enhancers/combobox.d.ts +17 -0
- package/dist/enhancers/context-menu.d.ts +19 -0
- package/dist/enhancers/date-picker.d.ts +8 -0
- package/dist/enhancers/drawer.d.ts +11 -0
- package/dist/enhancers/dropdown.d.ts +17 -0
- package/dist/enhancers/hover-card.d.ts +15 -0
- package/dist/enhancers/index.d.ts +42 -0
- package/dist/enhancers/modal.d.ts +16 -0
- package/dist/enhancers/scroll-area.d.ts +14 -0
- package/dist/enhancers/tabs.d.ts +26 -0
- package/dist/enhancers/test-helpers.d.ts +20 -0
- package/dist/enhancers/test-utils.d.ts +10 -0
- package/dist/enhancers/toast.d.ts +24 -0
- package/dist/enhancers/tooltip.d.ts +15 -0
- package/dist/enhancers/tree.d.ts +24 -0
- package/dist/enhancers/utils/click-away.d.ts +7 -0
- package/dist/enhancers/utils/create-overlay-enhancer.d.ts +14 -0
- package/dist/enhancers/utils/focus-trap.d.ts +9 -0
- package/dist/enhancers/utils/generate-id.d.ts +6 -0
- package/dist/enhancers/utils/keyboard-nav.d.ts +21 -0
- package/dist/enhancers/utils/position.d.ts +30 -0
- package/dist/fonts/index.d.ts +20 -0
- package/dist/index.d.ts +9 -0
- package/dist/init.d.ts +16 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.js +1 -0
- package/dist/plugins/postcss-soltana-treeshake.d.ts +10 -0
- package/dist/plugins/postcss-soltana-treeshake.js +149 -0
- package/dist/plugins/types.d.ts +9 -0
- package/dist/plugins/types.js +4 -0
- package/dist/soltana-ui.css +1 -0
- package/dist/soltana-ui.js +1702 -0
- package/dist/soltana-ui.umd.cjs +1 -0
- package/package.json +90 -0
- package/src/styles/_variables.scss +348 -0
- package/src/styles/base/_accessibility.scss +146 -0
- package/src/styles/base/_index.scss +12 -0
- package/src/styles/base/_register.scss +84 -0
- package/src/styles/base/_relief-system.scss +53 -0
- package/src/styles/base/_scrollbar.scss +40 -0
- package/src/styles/base/_transitions.scss +75 -0
- package/src/styles/base/_typography.scss +442 -0
- package/src/styles/components/_alert-dialogs.scss +75 -0
- package/src/styles/components/_badges.scss +215 -0
- package/src/styles/components/_buttons.scss +293 -0
- package/src/styles/components/_callouts.scss +99 -0
- package/src/styles/components/_cards.scss +97 -0
- package/src/styles/components/_carousels.scss +108 -0
- package/src/styles/components/_closes.scss +63 -0
- package/src/styles/components/_code.scss +75 -0
- package/src/styles/components/_collapsibles.scss +61 -0
- package/src/styles/components/_color-pickers.scss +211 -0
- package/src/styles/components/_comboboxes.scss +88 -0
- package/src/styles/components/_context-menus.scss +82 -0
- package/src/styles/components/_date-pickers.scss +165 -0
- package/src/styles/components/_feedback.scss +354 -0
- package/src/styles/components/_figures.scss +52 -0
- package/src/styles/components/_heros.scss +83 -0
- package/src/styles/components/_hover-cards.scss +55 -0
- package/src/styles/components/_images.scss +71 -0
- package/src/styles/components/_index.scss +41 -0
- package/src/styles/components/_indicators.scss +403 -0
- package/src/styles/components/_inputs.scss +409 -0
- package/src/styles/components/_layouts.scss +139 -0
- package/src/styles/components/_lists.scss +135 -0
- package/src/styles/components/_menus.scss +195 -0
- package/src/styles/components/_navigation.scss +325 -0
- package/src/styles/components/_overlays.scss +233 -0
- package/src/styles/components/_scroll-areas.scss +53 -0
- package/src/styles/components/_segmented-controls.scss +75 -0
- package/src/styles/components/_tables.scss +137 -0
- package/src/styles/components/_toasts.scss +111 -0
- package/src/styles/components/_toggles.scss +57 -0
- package/src/styles/components/_trees.scss +123 -0
- package/src/styles/decorative/_classical.scss +196 -0
- package/src/styles/decorative/_index.scss +7 -0
- package/src/styles/finishes/_index.scss +55 -0
- package/src/styles/index.scss +30 -0
- package/src/styles/reliefs/_index.scss +66 -0
- package/src/styles/reliefs/_neumorphic-tables.scss +92 -0
- package/src/styles/themes/_dark.scss +130 -0
- package/src/styles/themes/_index.scss +3 -0
- package/src/styles/themes/_light.scss +122 -0
- package/src/styles/themes/_sepia.scss +121 -0
- package/src/styles/utilities/_index.scss +13 -0
- package/src/styles/utilities/_layout.scss +100 -0
- package/src/styles/utilities/_mixins.scss +410 -0
- package/src/styles/utilities/_responsive.scss +46 -0
- package/src/styles/utilities/_sizing.scss +62 -0
- package/src/styles/utilities/_spacing.scss +12 -0
- package/src/styles/utilities/_visual.scss +436 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../config/types.js';
|
|
2
|
+
export declare const HOVER_CARD_SELECTOR = "[data-sol-hover-card]";
|
|
3
|
+
/**
|
|
4
|
+
* Enhance all `[data-sol-hover-card]` elements with hover-triggered
|
|
5
|
+
* floating card behavior.
|
|
6
|
+
*
|
|
7
|
+
* Expected structure:
|
|
8
|
+
* ```html
|
|
9
|
+
* <div data-sol-hover-card class="hover-card">
|
|
10
|
+
* <span class="hover-card-trigger">Hover me</span>
|
|
11
|
+
* <div class="hover-card-content">Rich content</div>
|
|
12
|
+
* </div>
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function initHoverCards(options?: EnhancerOptions): EnhancerCleanup;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../config/types.js';
|
|
2
|
+
import { initModals } from './modal.js';
|
|
3
|
+
import { initTabs } from './tabs.js';
|
|
4
|
+
import { initTooltips } from './tooltip.js';
|
|
5
|
+
import { initAccordions } from './accordion.js';
|
|
6
|
+
import { initDropdowns } from './dropdown.js';
|
|
7
|
+
import { initDrawers } from './drawer.js';
|
|
8
|
+
import { initToasts, showToast, dismissToast } from './toast.js';
|
|
9
|
+
import { initCollapsibles } from './collapsible.js';
|
|
10
|
+
import { initComboboxes } from './combobox.js';
|
|
11
|
+
import { initHoverCards } from './hover-card.js';
|
|
12
|
+
import { initContextMenus } from './context-menu.js';
|
|
13
|
+
import { initCarousels } from './carousel.js';
|
|
14
|
+
import { initScrollAreas } from './scroll-area.js';
|
|
15
|
+
import { initDatePickers } from './date-picker.js';
|
|
16
|
+
import { initColorPickers } from './color-picker.js';
|
|
17
|
+
import { initTrees } from './tree.js';
|
|
18
|
+
export { initModals, initTabs, initTooltips };
|
|
19
|
+
export { initAccordions, initDropdowns, initDrawers, initToasts };
|
|
20
|
+
export { showToast, dismissToast };
|
|
21
|
+
export { initCollapsibles, initComboboxes, initHoverCards };
|
|
22
|
+
export { initContextMenus, initCarousels, initScrollAreas };
|
|
23
|
+
export { initDatePickers, initColorPickers, initTrees };
|
|
24
|
+
export { MODAL_SELECTOR, MODAL_OPEN_SELECTOR } from './modal.js';
|
|
25
|
+
export { TABS_SELECTOR } from './tabs.js';
|
|
26
|
+
export { TOOLTIP_SELECTOR } from './tooltip.js';
|
|
27
|
+
export { ACCORDION_SELECTOR } from './accordion.js';
|
|
28
|
+
export { DROPDOWN_SELECTOR } from './dropdown.js';
|
|
29
|
+
export { DRAWER_SELECTOR, DRAWER_OPEN_SELECTOR } from './drawer.js';
|
|
30
|
+
export { TOAST_CONTAINER_SELECTOR } from './toast.js';
|
|
31
|
+
export { COLLAPSIBLE_SELECTOR } from './collapsible.js';
|
|
32
|
+
export { COMBOBOX_SELECTOR } from './combobox.js';
|
|
33
|
+
export { HOVER_CARD_SELECTOR } from './hover-card.js';
|
|
34
|
+
export { CONTEXT_MENU_SELECTOR } from './context-menu.js';
|
|
35
|
+
export { CAROUSEL_SELECTOR } from './carousel.js';
|
|
36
|
+
export { SCROLL_AREA_SELECTOR } from './scroll-area.js';
|
|
37
|
+
export { DATE_PICKER_SELECTOR } from './date-picker.js';
|
|
38
|
+
export { COLOR_PICKER_SELECTOR } from './color-picker.js';
|
|
39
|
+
export { TREE_SELECTOR } from './tree.js';
|
|
40
|
+
export type { ToastOptions, ToastType, ToastPosition } from './toast.js';
|
|
41
|
+
/** Initialize all enhancers. Call after DOM content is loaded. */
|
|
42
|
+
export declare function initAll(options?: EnhancerOptions): EnhancerCleanup;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const MODAL_SELECTOR = "[data-sol-modal]";
|
|
2
|
+
export declare const MODAL_OPEN_SELECTOR = "[data-modal-open]";
|
|
3
|
+
/**
|
|
4
|
+
* Enhance all `[data-sol-modal]` elements with open/close, focus trapping,
|
|
5
|
+
* Escape key, and backdrop click behavior.
|
|
6
|
+
*
|
|
7
|
+
* Open triggers: elements with `[data-modal-open="<modal-id>"]`.
|
|
8
|
+
* Close triggers: elements with `[data-modal-close]` inside the modal.
|
|
9
|
+
* Adds the `.sol-modal-open` class to `document.body` while any modal is open
|
|
10
|
+
* to prevent background scrolling.
|
|
11
|
+
*
|
|
12
|
+
* @param options - Optional scoping and selector overrides.
|
|
13
|
+
* @returns Cleanup handle — call `destroy()` to remove all listeners.
|
|
14
|
+
* Re-calling `initModals()` implicitly cleans up previous listeners.
|
|
15
|
+
*/
|
|
16
|
+
export declare const initModals: (options?: import('../index.js').EnhancerOptions) => import('../index.js').EnhancerCleanup;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../config/types.js';
|
|
2
|
+
export declare const SCROLL_AREA_SELECTOR = "[data-sol-scroll-area]";
|
|
3
|
+
/**
|
|
4
|
+
* Enhance all `[data-sol-scroll-area]` elements with auto-hiding
|
|
5
|
+
* scrollbar visibility on scroll.
|
|
6
|
+
*
|
|
7
|
+
* Expected structure:
|
|
8
|
+
* ```html
|
|
9
|
+
* <div data-sol-scroll-area class="scroll-area" style="max-height: 20rem;">
|
|
10
|
+
* <!-- Scrollable content -->
|
|
11
|
+
* </div>
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function initScrollAreas(options?: EnhancerOptions): EnhancerCleanup;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../config/types.js';
|
|
2
|
+
export declare const TABS_SELECTOR = "[data-sol-tabs]";
|
|
3
|
+
/**
|
|
4
|
+
* Enhance all `[data-sol-tabs]` elements with tab switching, keyboard
|
|
5
|
+
* navigation, and ARIA attributes.
|
|
6
|
+
*
|
|
7
|
+
* Expected structure:
|
|
8
|
+
* ```html
|
|
9
|
+
* <div data-sol-tabs>
|
|
10
|
+
* <div role="tablist">
|
|
11
|
+
* <button role="tab" aria-selected="true">Tab 1</button>
|
|
12
|
+
* <button role="tab">Tab 2</button>
|
|
13
|
+
* </div>
|
|
14
|
+
* <div role="tabpanel">Panel 1</div>
|
|
15
|
+
* <div role="tabpanel" hidden>Panel 2</div>
|
|
16
|
+
* </div>
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Mutates each tab container by setting `id`, `aria-controls`, and
|
|
20
|
+
* `aria-labelledby` attributes on tabs and panels.
|
|
21
|
+
*
|
|
22
|
+
* @param options - Optional scoping and selector overrides.
|
|
23
|
+
* @returns Cleanup handle — call `destroy()` to remove all listeners.
|
|
24
|
+
* Re-calling `initTabs()` implicitly cleans up previous listeners.
|
|
25
|
+
*/
|
|
26
|
+
export declare function initTabs(options?: EnhancerOptions): EnhancerCleanup;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
import { EnhancerCleanup } from '../config/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Verifies that re-calling an enhancer init function does not duplicate listeners.
|
|
5
|
+
* Tests the singleton behavior pattern used across all enhancers.
|
|
6
|
+
*
|
|
7
|
+
* @param initFn - The enhancer init function to test (e.g., initTabs, initModals)
|
|
8
|
+
* @param setupDOM - Callback to create the necessary DOM structure and return the trigger element
|
|
9
|
+
* @param verify - Callback to verify the expected behavior after triggering
|
|
10
|
+
*/
|
|
11
|
+
export declare function testSingletonBehavior(initFn: () => EnhancerCleanup, setupDOM: () => HTMLElement, verify: (trigger: HTMLElement) => void): void;
|
|
12
|
+
/**
|
|
13
|
+
* Mocks getBoundingClientRect on an HTML element with default positioning values.
|
|
14
|
+
* Useful for tests that require element dimensions and positioning (e.g., tooltips, popovers).
|
|
15
|
+
*
|
|
16
|
+
* @param element - The element to mock getBoundingClientRect on
|
|
17
|
+
* @param overrides - Optional partial DOMRect properties to override defaults
|
|
18
|
+
* @returns The vitest spy instance
|
|
19
|
+
*/
|
|
20
|
+
export declare function mockBoundingClientRect(element: HTMLElement, overrides?: Partial<DOMRect>): ReturnType<typeof vi.spyOn>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type InitFn = (opts?: {
|
|
2
|
+
root?: Element;
|
|
3
|
+
}) => {
|
|
4
|
+
destroy: () => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function testDestroyPreventsInteraction(init: InitFn, createDOM: () => HTMLElement, triggerAction: (el: HTMLElement) => void, verifyInactive: (el: HTMLElement) => void): void;
|
|
7
|
+
export declare function testIdempotentInit(init: InitFn, createDOM: () => HTMLElement, act: (el: HTMLElement) => void): void;
|
|
8
|
+
export declare function testNoMatchGraceful(init: InitFn): void;
|
|
9
|
+
export declare function testCustomRoot(init: InitFn, setupInRoot: (root: HTMLElement) => void, verify: (root: HTMLElement) => void): void;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../config/types.js';
|
|
2
|
+
export declare const TOAST_CONTAINER_SELECTOR = "[data-sol-toast-container]";
|
|
3
|
+
export type ToastType = 'success' | 'warning' | 'error' | 'info';
|
|
4
|
+
export type ToastPosition = 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center';
|
|
5
|
+
export interface ToastOptions {
|
|
6
|
+
message: string;
|
|
7
|
+
type?: ToastType;
|
|
8
|
+
duration?: number;
|
|
9
|
+
position?: ToastPosition;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Programmatically show a toast notification.
|
|
13
|
+
* Creates DOM, animates in, and auto-dismisses after `duration` ms (default 5000).
|
|
14
|
+
*/
|
|
15
|
+
export declare function showToast(opts: ToastOptions): HTMLElement;
|
|
16
|
+
/**
|
|
17
|
+
* Dismiss a specific toast element.
|
|
18
|
+
*/
|
|
19
|
+
export declare function dismissToast(toast: HTMLElement): void;
|
|
20
|
+
/**
|
|
21
|
+
* Enhance all `[data-sol-toast-container]` elements with ARIA attributes
|
|
22
|
+
* and close button behavior on existing toasts.
|
|
23
|
+
*/
|
|
24
|
+
export declare function initToasts(options?: EnhancerOptions): EnhancerCleanup;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../config/types.js';
|
|
2
|
+
export declare const TOOLTIP_SELECTOR = "[data-sol-tooltip]";
|
|
3
|
+
/**
|
|
4
|
+
* Enhance all `[data-sol-tooltip]` elements with positioned tooltips.
|
|
5
|
+
*
|
|
6
|
+
* Attaches mouseenter/focus listeners that show a tooltip, and
|
|
7
|
+
* mouseleave/blur/Escape listeners that hide it. Creates a single shared
|
|
8
|
+
* tooltip element appended to `document.body`.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Optional scoping and selector overrides.
|
|
11
|
+
* @returns Cleanup handle — call `destroy()` to remove all listeners and the
|
|
12
|
+
* tooltip element. Re-calling `initTooltips()` implicitly cleans up
|
|
13
|
+
* previous listeners.
|
|
14
|
+
*/
|
|
15
|
+
export declare function initTooltips(options?: EnhancerOptions): EnhancerCleanup;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../config/types.js';
|
|
2
|
+
export declare const TREE_SELECTOR = "[data-sol-tree]";
|
|
3
|
+
/**
|
|
4
|
+
* Enhance all `[data-sol-tree]` elements with expand/collapse and
|
|
5
|
+
* keyboard navigation behavior.
|
|
6
|
+
*
|
|
7
|
+
* Expected structure:
|
|
8
|
+
* ```html
|
|
9
|
+
* <div data-sol-tree class="tree" role="tree">
|
|
10
|
+
* <div class="tree-branch tree-node" role="treeitem">
|
|
11
|
+
* <div class="tree-node-content">
|
|
12
|
+
* <button class="tree-toggle"></button>
|
|
13
|
+
* Folder
|
|
14
|
+
* </div>
|
|
15
|
+
* <div class="tree-children">
|
|
16
|
+
* <div class="tree-leaf tree-node" role="treeitem">
|
|
17
|
+
* <div class="tree-node-content">File</div>
|
|
18
|
+
* </div>
|
|
19
|
+
* </div>
|
|
20
|
+
* </div>
|
|
21
|
+
* </div>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function initTrees(options?: EnhancerOptions): EnhancerCleanup;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register a callback that fires when a click occurs outside `element`.
|
|
3
|
+
* Uses the provided `AbortSignal` for cleanup — no manual teardown needed.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export declare function onClickAway(element: HTMLElement, callback: () => void, signal: AbortSignal): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EnhancerCleanup, EnhancerOptions } from '../../config/types.js';
|
|
2
|
+
interface OverlayConfig {
|
|
3
|
+
overlaySelector: string;
|
|
4
|
+
openTriggerAttr: string;
|
|
5
|
+
closeTriggerAttr: string;
|
|
6
|
+
bodyOpenClass: string;
|
|
7
|
+
contentSelector: string;
|
|
8
|
+
childElementsToActivate: string[];
|
|
9
|
+
checkOverlayAsBackdrop: boolean;
|
|
10
|
+
backdropSelector: string;
|
|
11
|
+
setupAria?: (overlay: HTMLElement) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createOverlayEnhancer(config: OverlayConfig): (options?: EnhancerOptions) => EnhancerCleanup;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const FOCUSABLE: string;
|
|
2
|
+
/**
|
|
3
|
+
* Trap Tab/Shift+Tab focus within a container element.
|
|
4
|
+
* Call from a `keydown` handler when `e.key === 'Tab'`.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export declare function trapFocus(container: HTMLElement, event: KeyboardEvent): void;
|
|
9
|
+
export { FOCUSABLE };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** @internal */
|
|
2
|
+
export interface KeyboardNavOptions {
|
|
3
|
+
/** Container element holding the navigable items. */
|
|
4
|
+
container: HTMLElement;
|
|
5
|
+
/** CSS selector for individual navigable items within the container. */
|
|
6
|
+
itemSelector: string;
|
|
7
|
+
/** Navigation direction supported by the component. */
|
|
8
|
+
orientation: 'vertical' | 'horizontal' | 'both';
|
|
9
|
+
/** Wrap from last item to first (and vice versa). Defaults to true. */
|
|
10
|
+
wrap?: boolean;
|
|
11
|
+
/** Callback invoked when an item is activated (Enter/Space). */
|
|
12
|
+
onActivate?: (item: HTMLElement) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Handle a keydown event for arrow-key navigation within a list of items.
|
|
16
|
+
* Manages `aria-activedescendant`-style focus by calling `focus()` on
|
|
17
|
+
* the target item. Returns true if the event was handled.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleKeyboardNav(options: KeyboardNavOptions, event: KeyboardEvent): boolean;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type Placement = 'top' | 'bottom' | 'left' | 'right';
|
|
2
|
+
export interface PositionOptions {
|
|
3
|
+
/** Anchor element or fixed coordinates (e.g. for context menus). */
|
|
4
|
+
anchor: HTMLElement | {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
};
|
|
8
|
+
/** Floating element to position. */
|
|
9
|
+
floating: HTMLElement;
|
|
10
|
+
/** Preferred placement relative to the anchor. */
|
|
11
|
+
placement: Placement;
|
|
12
|
+
/** Gap between anchor and floating element in pixels. */
|
|
13
|
+
gap?: number;
|
|
14
|
+
/** Minimum distance from viewport edges in pixels. */
|
|
15
|
+
viewportPadding?: number;
|
|
16
|
+
/** Auto-flip to opposite side when clipped by viewport. */
|
|
17
|
+
flip?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface PositionResult {
|
|
20
|
+
top: number;
|
|
21
|
+
left: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Compute absolute position for a floating element relative to an anchor.
|
|
25
|
+
* Supports viewport clamping and optional flip when the preferred placement
|
|
26
|
+
* would be clipped.
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export declare function computePosition(options: PositionOptions): PositionResult;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const DEFAULT_FONT_URL: string;
|
|
2
|
+
/**
|
|
3
|
+
* Inject a font stylesheet (and optional preconnect hints) into `<head>`.
|
|
4
|
+
*
|
|
5
|
+
* Idempotent: only the first call injects elements; subsequent calls are
|
|
6
|
+
* no-ops. The internal loaded flag is reset when `destroy()` is called on
|
|
7
|
+
* the Soltana instance, allowing re-initialization.
|
|
8
|
+
*
|
|
9
|
+
* @param url - Font CSS URL. Defaults to the bundled Google Fonts URL
|
|
10
|
+
* containing Cinzel, Cinzel Decorative, Raleway, and JetBrains
|
|
11
|
+
* Mono. When the URL
|
|
12
|
+
* points to `fonts.googleapis.com`, preconnect links are also
|
|
13
|
+
* injected automatically.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadSoltanaFonts(url?: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Remove injected font elements and reset loaded flag. Called by destroy().
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export declare function _resetFontLoader(): void;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { initSoltana, DEFAULT_STATE } from './init.js';
|
|
2
|
+
export { BUILT_IN_THEMES, BUILT_IN_RELIEFS, BUILT_IN_FINISHES } from './config/index.js';
|
|
3
|
+
/** Advanced exports for runtime validation, testing, and custom integrations. */
|
|
4
|
+
export { VALID_THEMES, VALID_RELIEFS, VALID_FINISHES } from './config/index.js';
|
|
5
|
+
export type { SoltanaConfig, SoltanaInitOptions, SoltanaInstance, SoltanaChangeDetail, EnhancerCleanup, EnhancerOptions, Theme, Relief, Finish, BuiltInTheme, BuiltInRelief, BuiltInFinish, TierName, SoltanaChangeType, ThemeSeed, RegisterThemeOptions, RegisterReliefOptions, RegisterFinishOptions, TierRegistration, } from './config/index.js';
|
|
6
|
+
export { initModals, initTabs, initTooltips, initAccordions, initDropdowns, initDrawers, initToasts, showToast, dismissToast, initCollapsibles, initComboboxes, initHoverCards, initContextMenus, initCarousels, initScrollAreas, initDatePickers, initColorPickers, initTrees, initAll, MODAL_SELECTOR, MODAL_OPEN_SELECTOR, TABS_SELECTOR, TOOLTIP_SELECTOR, ACCORDION_SELECTOR, DROPDOWN_SELECTOR, DRAWER_SELECTOR, DRAWER_OPEN_SELECTOR, TOAST_CONTAINER_SELECTOR, COLLAPSIBLE_SELECTOR, COMBOBOX_SELECTOR, HOVER_CARD_SELECTOR, CONTEXT_MENU_SELECTOR, CAROUSEL_SELECTOR, SCROLL_AREA_SELECTOR, DATE_PICKER_SELECTOR, COLOR_PICKER_SELECTOR, TREE_SELECTOR, } from './enhancers/index.js';
|
|
7
|
+
export type { ToastOptions, ToastType, ToastPosition } from './enhancers/index.js';
|
|
8
|
+
export { loadSoltanaFonts, DEFAULT_FONT_URL } from './fonts/index.js';
|
|
9
|
+
export declare const version: string;
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SoltanaConfig, SoltanaInitOptions, SoltanaInstance } from './config/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default tier configuration used when no overrides are provided.
|
|
4
|
+
*
|
|
5
|
+
* - `theme: 'auto'` resolves to `'dark'` or `'light'` via `prefers-color-scheme`.
|
|
6
|
+
* - `relief: 'flat'` is the minimal baseline (no shadow effects).
|
|
7
|
+
* - `finish: 'matte'` is the zero-effect baseline (no blur, sheen, or tint).
|
|
8
|
+
*
|
|
9
|
+
* All built-in tier combinations (3 themes + auto resolver, 4 reliefs, 4 finishes) are valid.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_STATE: Readonly<SoltanaConfig>;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the Soltana design system.
|
|
14
|
+
* Sets data attributes on <html> to activate SCSS theme/relief/finish selectors.
|
|
15
|
+
*/
|
|
16
|
+
export declare function initSoltana(userConfig?: Partial<SoltanaConfig & SoltanaInitOptions>): SoltanaInstance;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as soltanaTreeshake } from './postcss-soltana-treeshake.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Plugin } from 'postcss';
|
|
2
|
+
import type { SoltanaTreeshakeOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* PostCSS plugin that strips CSS rules referencing excluded tier values.
|
|
5
|
+
*/
|
|
6
|
+
declare function soltanaTreeshake(options?: SoltanaTreeshakeOptions): Plugin;
|
|
7
|
+
declare namespace soltanaTreeshake {
|
|
8
|
+
var postcss: true;
|
|
9
|
+
}
|
|
10
|
+
export default soltanaTreeshake;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// PostCSS Soltana Tree-Shake Plugin
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Strips CSS rules referencing excluded built-in tier values from the compiled
|
|
5
|
+
// output. Only explicitly excluded built-in values are removed — custom tier
|
|
6
|
+
// values and non-tier selectors are never touched.
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
import { BUILT_IN_THEMES, BUILT_IN_RELIEFS, BUILT_IN_FINISHES } from '../config/index.js';
|
|
9
|
+
const BUILT_IN = {
|
|
10
|
+
theme: BUILT_IN_THEMES,
|
|
11
|
+
relief: BUILT_IN_RELIEFS,
|
|
12
|
+
finish: BUILT_IN_FINISHES,
|
|
13
|
+
};
|
|
14
|
+
// Maps plural config keys to singular tier names used in selectors
|
|
15
|
+
const TIER_KEY_MAP = {
|
|
16
|
+
themes: 'theme',
|
|
17
|
+
reliefs: 'relief',
|
|
18
|
+
finishes: 'finish',
|
|
19
|
+
};
|
|
20
|
+
// Matches [data-tier='value'] in a selector fragment (global for all occurrences)
|
|
21
|
+
const DATA_ATTR_RE = /\[data-(theme|relief|finish)='([^']+)'\]/g;
|
|
22
|
+
// Matches .tier-value in a selector fragment
|
|
23
|
+
const CLASS_RE = /\.(theme|relief|finish)-([\w-]+)/;
|
|
24
|
+
// Matches [data-tier='value'] that appears inside :not()
|
|
25
|
+
const NEGATED_ATTR_RE = /:not\([^)]*\[data-(theme|relief|finish)='[^']+'\][^)]*\)/g;
|
|
26
|
+
function isTierConfig(value) {
|
|
27
|
+
if (typeof value !== 'object' || value === null)
|
|
28
|
+
return false;
|
|
29
|
+
const obj = value;
|
|
30
|
+
if ('include' in obj && !Array.isArray(obj.include))
|
|
31
|
+
return false;
|
|
32
|
+
if ('exclude' in obj && !Array.isArray(obj.exclude))
|
|
33
|
+
return false;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compute the set of tier values to exclude from output.
|
|
38
|
+
*/
|
|
39
|
+
function buildExcludeSet(options) {
|
|
40
|
+
const excludes = new Map();
|
|
41
|
+
for (const [pluralKey, value] of Object.entries(options)) {
|
|
42
|
+
const tier = TIER_KEY_MAP[pluralKey];
|
|
43
|
+
if (!tier || !(tier in BUILT_IN))
|
|
44
|
+
continue;
|
|
45
|
+
if (!isTierConfig(value))
|
|
46
|
+
continue;
|
|
47
|
+
const tierConfig = value;
|
|
48
|
+
const builtIn = BUILT_IN[tier];
|
|
49
|
+
if (tierConfig.include && tierConfig.exclude) {
|
|
50
|
+
console.warn(`[soltana] Tier "${tier}" specifies both include and exclude; exclude will be ignored`);
|
|
51
|
+
}
|
|
52
|
+
let excluded;
|
|
53
|
+
const builtInSet = new Set(builtIn);
|
|
54
|
+
if (tierConfig.include) {
|
|
55
|
+
// Warn on unrecognized include values
|
|
56
|
+
for (const v of tierConfig.include) {
|
|
57
|
+
if (!builtInSet.has(v)) {
|
|
58
|
+
console.warn(`[soltana] Treeshake: include value "${v}" is not a built-in ${tier}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Exclude everything built-in that isn't in the include list
|
|
62
|
+
const included = new Set(tierConfig.include);
|
|
63
|
+
excluded = builtIn.filter((v) => !included.has(v));
|
|
64
|
+
}
|
|
65
|
+
else if (tierConfig.exclude) {
|
|
66
|
+
// Warn on unrecognized exclude values
|
|
67
|
+
for (const v of tierConfig.exclude) {
|
|
68
|
+
if (!builtInSet.has(v)) {
|
|
69
|
+
console.warn(`[soltana] Treeshake: exclude value "${v}" is not a built-in ${tier}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Exclude only explicitly listed values (intersected with built-in)
|
|
73
|
+
excluded = tierConfig.exclude.filter((v) => builtInSet.has(v));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (excluded.length > 0) {
|
|
79
|
+
excludes.set(tier, new Set(excluded));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return excludes;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Extract all tier + value pairs from a single selector fragment.
|
|
86
|
+
* Returns an empty array for neutral selectors (no tier reference).
|
|
87
|
+
* Ignores tier references inside :not() — those are negations, not positive matches.
|
|
88
|
+
*/
|
|
89
|
+
function extractTierRefs(fragment) {
|
|
90
|
+
const stripped = fragment.replace(NEGATED_ATTR_RE, '');
|
|
91
|
+
const refs = [];
|
|
92
|
+
DATA_ATTR_RE.lastIndex = 0;
|
|
93
|
+
let match;
|
|
94
|
+
while ((match = DATA_ATTR_RE.exec(stripped)) !== null) {
|
|
95
|
+
refs.push({ tier: match[1], value: match[2] });
|
|
96
|
+
}
|
|
97
|
+
const classMatch = CLASS_RE.exec(stripped);
|
|
98
|
+
if (classMatch) {
|
|
99
|
+
refs.push({ tier: classMatch[1], value: classMatch[2] });
|
|
100
|
+
}
|
|
101
|
+
return refs;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Determine whether a selector fragment should be excluded.
|
|
105
|
+
* A fragment is excluded if any of its tier references targets an excluded value.
|
|
106
|
+
*/
|
|
107
|
+
function isExcluded(fragment, excludes) {
|
|
108
|
+
const refs = extractTierRefs(fragment);
|
|
109
|
+
if (refs.length === 0)
|
|
110
|
+
return false; // Neutral selector — never excluded
|
|
111
|
+
return refs.some((ref) => {
|
|
112
|
+
const tierExcludes = excludes.get(ref.tier);
|
|
113
|
+
return tierExcludes?.has(ref.value) ?? false;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* PostCSS plugin that strips CSS rules referencing excluded tier values.
|
|
118
|
+
*/
|
|
119
|
+
function soltanaTreeshake(options = {}) {
|
|
120
|
+
const excludes = buildExcludeSet(options);
|
|
121
|
+
return {
|
|
122
|
+
postcssPlugin: 'postcss-soltana-treeshake',
|
|
123
|
+
Once(root) {
|
|
124
|
+
if (excludes.size === 0)
|
|
125
|
+
return;
|
|
126
|
+
root.walkRules((rule) => {
|
|
127
|
+
// Never touch @keyframes children
|
|
128
|
+
if (rule.parent && 'name' in rule.parent && rule.parent.name === 'keyframes') {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const fragments = rule.selectors;
|
|
132
|
+
const kept = [];
|
|
133
|
+
for (const fragment of fragments) {
|
|
134
|
+
if (!isExcluded(fragment, excludes)) {
|
|
135
|
+
kept.push(fragment);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (kept.length === 0) {
|
|
139
|
+
rule.remove();
|
|
140
|
+
}
|
|
141
|
+
else if (kept.length < fragments.length) {
|
|
142
|
+
rule.selectors = kept;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
soltanaTreeshake.postcss = true;
|
|
149
|
+
export default soltanaTreeshake;
|