bref-ui 0.2.5 → 0.2.7

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 CHANGED
@@ -62,6 +62,7 @@ Bref handles:
62
62
  - [x] Morphing Shapes
63
63
  - [x] Textual
64
64
  - [x] Tree View
65
+ - [x] Pill
65
66
  - [-] Inputs
66
67
  - [x] Text Input (single line)
67
68
  - [x] Area Text Input
@@ -7,3 +7,5 @@ export * from './tree-view/index.ts';
7
7
  export * from './text-input/index.ts';
8
8
  export * from './slider/index.ts';
9
9
  export * from './progress-bar/index.ts';
10
+ export * from './pill/index.ts';
11
+ export * from './select/index.ts';
@@ -7,3 +7,5 @@ export * from "./tree-view/index.js";
7
7
  export * from "./text-input/index.js";
8
8
  export * from "./slider/index.js";
9
9
  export * from "./progress-bar/index.js";
10
+ export * from "./pill/index.js";
11
+ export * from "./select/index.js";
@@ -0,0 +1 @@
1
+ export { default as Pill } from './pill.svelte';
@@ -0,0 +1 @@
1
+ export { default as Pill } from './pill.svelte';
@@ -0,0 +1,146 @@
1
+ <script lang="ts">
2
+ import type { SvelteHTMLElements } from 'svelte/elements';
3
+ import type { PillProps } from './types.js';
4
+ import Icon from '../icon/icon.svelte';
5
+
6
+ const {
7
+ label,
8
+ size = 'medium',
9
+ color = 'primary',
10
+ variant = 'filled',
11
+ icon
12
+ }: PillProps = $props();
13
+ </script>
14
+
15
+ <div class={`${size} ${color} ${variant}`}>
16
+ {#if icon}
17
+ <Icon contrastMode={variant === 'filled'} {color} {...icon} {size} />
18
+ {/if}
19
+ <span>{label}</span>
20
+ </div>
21
+
22
+ <style>
23
+ div {
24
+ /* Size defaults (medium) */
25
+ --internal-pill-padding-y: calc(var(--spacing) * 0.375);
26
+ --internal-pill-padding-x: calc(var(--spacing) * 0.75);
27
+ --internal-pill-font-size: 1rem;
28
+
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ border: none;
33
+ flex-shrink: 0;
34
+ width: fit-content;
35
+ min-width: fit-content;
36
+ height: fit-content;
37
+ min-height: fit-content;
38
+ gap: 0.35em;
39
+ padding: var(--internal-pill-padding-y) var(--internal-pill-padding-x);
40
+ font-size: var(--internal-pill-font-size);
41
+ border-radius: 4rem;
42
+ }
43
+
44
+ span {
45
+ white-space: nowrap;
46
+ color: inherit;
47
+ }
48
+
49
+ /* Sizes - compact padding that scales proportionally */
50
+ .x-small {
51
+ --internal-pill-padding-y: calc(var(--spacing) * 0.125);
52
+ --internal-pill-padding-x: calc(var(--spacing) * 0.375);
53
+ --internal-pill-font-size: 0.75rem;
54
+ }
55
+
56
+ .small {
57
+ --internal-pill-padding-y: calc(var(--spacing) * 0.25);
58
+ --internal-pill-padding-x: calc(var(--spacing) * 0.5);
59
+ --internal-pill-font-size: 0.875rem;
60
+ }
61
+
62
+ .medium {
63
+ --internal-pill-padding-y: calc(var(--spacing) * 0.375);
64
+ --internal-pill-padding-x: calc(var(--spacing) * 0.75);
65
+ --internal-pill-font-size: 1rem;
66
+ }
67
+
68
+ .large {
69
+ --internal-pill-padding-y: calc(var(--spacing) * 0.5);
70
+ --internal-pill-padding-x: calc(var(--spacing) * 1);
71
+ --internal-pill-font-size: 1.125rem;
72
+ }
73
+
74
+ .x-large {
75
+ --internal-pill-padding-y: calc(var(--spacing) * 0.625);
76
+ --internal-pill-padding-x: calc(var(--spacing) * 1.25);
77
+ --internal-pill-font-size: 1.25rem;
78
+ }
79
+
80
+ /* Color mappings - set current color variables per color class */
81
+ .primary {
82
+ --internal-current-color: var(--color-primary);
83
+ --internal-current-color-soft: var(--color-primary-soft);
84
+ --internal-current-contrast: var(--color-primary-contrast);
85
+ }
86
+
87
+ .secondary {
88
+ --internal-current-color: var(--color-secondary);
89
+ --internal-current-color-soft: var(--color-secondary-soft);
90
+ --internal-current-contrast: var(--color-secondary-contrast);
91
+ }
92
+
93
+ .success {
94
+ --internal-current-color: var(--color-success);
95
+ --internal-current-color-soft: var(--color-success-soft);
96
+ --internal-current-contrast: var(--color-success-contrast);
97
+ }
98
+
99
+ .warning {
100
+ --internal-current-color: var(--color-warning);
101
+ --internal-current-color-soft: var(--color-warning-soft);
102
+ --internal-current-contrast: var(--color-warning-contrast);
103
+ }
104
+
105
+ .danger {
106
+ --internal-current-color: var(--color-danger);
107
+ --internal-current-color-soft: var(--color-danger-soft);
108
+ --internal-current-contrast: var(--color-danger-contrast);
109
+ }
110
+
111
+ .info {
112
+ --internal-current-color: var(--color-info);
113
+ --internal-current-color-soft: var(--color-info-soft);
114
+ --internal-current-contrast: var(--color-info-contrast);
115
+ }
116
+
117
+ .foreground {
118
+ --internal-current-color: var(--color-foreground);
119
+ --internal-current-color-soft: var(--color-background-saturated);
120
+ --internal-current-contrast: var(--color-background);
121
+ }
122
+
123
+ .background {
124
+ --internal-current-color: var(--color-background);
125
+ --internal-current-color-soft: var(--color-foreground-saturated);
126
+ --internal-current-contrast: var(--color-foreground);
127
+ }
128
+
129
+ /* Filled variant */
130
+ .filled {
131
+ background-color: var(--internal-current-color);
132
+ color: var(--internal-current-contrast);
133
+ }
134
+
135
+ /* Soft variant */
136
+ .soft {
137
+ background-color: var(--internal-current-color-soft);
138
+ color: var(--internal-current-color);
139
+ }
140
+
141
+ /* Ghost variant */
142
+ .ghost {
143
+ background-color: transparent;
144
+ color: var(--internal-current-color);
145
+ }
146
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { PillProps } from './types.ts';
2
+ declare const Pill: import("svelte").Component<PillProps, {}, "">;
3
+ type Pill = ReturnType<typeof Pill>;
4
+ export default Pill;
@@ -0,0 +1,9 @@
1
+ import type { IconProps } from '../icon/types.ts';
2
+ import type { Color, Size, Variant } from '../types.ts';
3
+ export interface PillProps {
4
+ label: string;
5
+ size?: Size;
6
+ color?: Color;
7
+ variant?: Variant;
8
+ icon?: Pick<IconProps, 'name' | 'filled' | 'ariaLabel'>;
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export { default as Select } from './select.svelte';
2
+ export * from './types.ts';
@@ -0,0 +1,2 @@
1
+ export { default as Select } from './select.svelte';
2
+ export * from "./types.js";
@@ -0,0 +1,139 @@
1
+ <script lang="ts">
2
+ import Icon from '../icon/icon.svelte';
3
+ import type { SelectProps } from './types.js';
4
+
5
+ let {
6
+ value,
7
+ options,
8
+ placeholder = 'Select...',
9
+ disabled = false,
10
+ onChange,
11
+ wide = false,
12
+ startIcon,
13
+ size = 'medium'
14
+ }: SelectProps = $props();
15
+
16
+ const handleChange = (e: Event) => onChange((e.currentTarget as HTMLSelectElement).value);
17
+
18
+ let select: HTMLSelectElement;
19
+
20
+ const triggerDropDown = (e: MouseEvent) => {
21
+ e.stopPropagation();
22
+ if (disabled) return;
23
+ select.focus();
24
+ select.showPicker();
25
+ };
26
+ </script>
27
+
28
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
29
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
30
+ <div class={size} class:wide class:disabled onclick={triggerDropDown}>
31
+ {#if startIcon}
32
+ <Icon {...startIcon} {size} />
33
+ {/if}
34
+ <select
35
+ {disabled}
36
+ {value}
37
+ onchange={handleChange}
38
+ onclick={(e) => e.stopPropagation()}
39
+ bind:this={select}
40
+ >
41
+ {#if placeholder && !value}
42
+ <option value="" disabled selected>{placeholder}</option>
43
+ {/if}
44
+ {#each options as option}
45
+ <option value={option.value}>
46
+ {option.label}
47
+ </option>
48
+ {/each}
49
+ </select>
50
+ <Icon name="arrow_drop_down" {size} onclick={triggerDropDown} />
51
+ </div>
52
+
53
+ <style>
54
+ div {
55
+ --internal-select-bg-opacity: 5%;
56
+ --internal-select-hover-opacity: 7%;
57
+ --internal-select-padding-y: calc(var(--spacing) * 0.5);
58
+ --internal-select-padding-x: calc(var(--spacing) * 0.75);
59
+ --internal-select-radius: calc(var(--border-radius) * 1);
60
+
61
+ display: flex;
62
+ cursor: pointer;
63
+ align-items: center;
64
+ gap: 0.25rem;
65
+ flex-shrink: 0;
66
+ padding: var(--internal-select-padding-y) var(--internal-select-padding-x);
67
+ border-radius: var(--internal-select-radius);
68
+ background-color: color-mix(
69
+ in srgb,
70
+ var(--color-foreground) var(--internal-select-bg-opacity),
71
+ transparent
72
+ );
73
+ transition: background-color 0.15s ease;
74
+ }
75
+
76
+ div:hover:not(.disabled) {
77
+ background-color: color-mix(
78
+ in srgb,
79
+ var(--color-foreground) var(--internal-select-hover-opacity),
80
+ transparent
81
+ );
82
+ }
83
+
84
+ div.wide {
85
+ width: 100%;
86
+ flex-shrink: 1;
87
+ }
88
+
89
+ div.disabled {
90
+ opacity: 0.5;
91
+ cursor: not-allowed;
92
+ }
93
+
94
+ div.disabled select {
95
+ cursor: not-allowed;
96
+ }
97
+
98
+ /* Size variants */
99
+ div.x-small {
100
+ --internal-select-padding-y: calc(var(--spacing) * 0.25);
101
+ --internal-select-padding-x: calc(var(--spacing) * 0.5);
102
+ --internal-select-radius: calc(var(--border-radius) * 0.75);
103
+ --select-font-size: 0.75rem;
104
+ }
105
+
106
+ div.small {
107
+ --internal-select-padding-y: calc(var(--spacing) * 0.375);
108
+ --internal-select-padding-x: calc(var(--spacing) * 0.75);
109
+ --internal-select-radius: var(--border-radius);
110
+ --select-font-size: 0.875rem;
111
+ }
112
+
113
+ div.medium {
114
+ --internal-select-padding-y: calc(var(--spacing) * 0.5);
115
+ --internal-select-padding-x: calc(var(--spacing) * 1);
116
+ --internal-select-radius: calc(var(--border-radius) * 1.25);
117
+ --select-font-size: 1rem;
118
+ }
119
+
120
+ div.large {
121
+ --internal-select-padding-y: calc(var(--spacing) * 0.625);
122
+ --internal-select-padding-x: calc(var(--spacing) * 1.25);
123
+ --internal-select-radius: calc(var(--border-radius) * 1.5);
124
+ --select-font-size: 1.125rem;
125
+ }
126
+
127
+ div.x-large {
128
+ --internal-select-padding-y: calc(var(--spacing) * 0.75);
129
+ --internal-select-padding-x: calc(var(--spacing) * 1.5);
130
+ --internal-select-radius: calc(var(--border-radius) * 2);
131
+ --select-font-size: 1.25rem;
132
+ }
133
+
134
+ select {
135
+ all: unset;
136
+ font-size: var(--select-font-size);
137
+ flex: 1;
138
+ }
139
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { SelectProps } from './types.ts';
2
+ declare const Select: import("svelte").Component<SelectProps, {}, "">;
3
+ type Select = ReturnType<typeof Select>;
4
+ export default Select;
@@ -0,0 +1,16 @@
1
+ import type { Size } from '../types.ts';
2
+ import type { IconProps } from '../icon/types.ts';
3
+ export interface SelectOptionProps {
4
+ value: string;
5
+ label: string;
6
+ }
7
+ export interface SelectProps {
8
+ value: string;
9
+ options: SelectOptionProps[];
10
+ placeholder?: string;
11
+ disabled?: boolean;
12
+ onChange: (value: string) => void;
13
+ wide?: boolean;
14
+ startIcon?: Exclude<IconProps, 'size'>;
15
+ size?: Size;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bref-ui",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "A Svelte UI component library using scoped CSS - minimal and flexible",
5
5
  "license": "MIT",
6
6
  "author": "feuerstein",