@miozu/jera 0.8.4 → 0.8.6

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/CLAUDE.md CHANGED
@@ -34,7 +34,7 @@ Uses Base16 naming: `base00`-`base0F` (hex digits).
34
34
 
35
35
  ## Component API Quick Reference
36
36
 
37
- **Button:** `variant` (primary|secondary|ghost|outline|danger|success), `size` (xs-xl), `disabled`, `loading`, `href`
37
+ **Button:** `variant` (primary|secondary|ghost|outline|danger|success|warning|info), `size` (xs|sm|md|lg), `disabled`, `loading`, `href`, `fullWidth`
38
38
 
39
39
  **Input:** `bind:value`, `type`, `placeholder`, `disabled`, `required`
40
40
 
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@miozu/jera",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Zero-dependency, AI-first component library for Svelte 5",
5
5
  "type": "module",
6
+ "sideEffects": false,
6
7
  "scripts": {
7
8
  "prepublishOnly": "echo 'Publishing @miozu/jera...' && test -f src/index.js"
8
9
  },
@@ -12,6 +13,42 @@
12
13
  "svelte": "./src/index.js",
13
14
  "default": "./src/index.js"
14
15
  },
16
+ "./components/primitives/*": {
17
+ "svelte": "./src/components/primitives/*.svelte",
18
+ "default": "./src/components/primitives/*.svelte"
19
+ },
20
+ "./components/forms/*": {
21
+ "svelte": "./src/components/forms/*.svelte",
22
+ "default": "./src/components/forms/*.svelte"
23
+ },
24
+ "./components/feedback/*": {
25
+ "svelte": "./src/components/feedback/*.svelte",
26
+ "default": "./src/components/feedback/*.svelte"
27
+ },
28
+ "./components/feedback/Toast": {
29
+ "svelte": "./src/components/feedback/Toast.svelte",
30
+ "default": "./src/components/feedback/Toast.svelte"
31
+ },
32
+ "./components/overlays/*": {
33
+ "svelte": "./src/components/overlays/*.svelte",
34
+ "default": "./src/components/overlays/*.svelte"
35
+ },
36
+ "./components/navigation/*": {
37
+ "svelte": "./src/components/navigation/*.svelte",
38
+ "default": "./src/components/navigation/*.svelte"
39
+ },
40
+ "./components/navigation/blocks/*": {
41
+ "svelte": "./src/components/navigation/blocks/*.svelte",
42
+ "default": "./src/components/navigation/blocks/*.svelte"
43
+ },
44
+ "./components/layout/*": {
45
+ "svelte": "./src/components/layout/*.svelte",
46
+ "default": "./src/components/layout/*.svelte"
47
+ },
48
+ "./components/docs/*": {
49
+ "svelte": "./src/components/docs/*.svelte",
50
+ "default": "./src/components/docs/*.svelte"
51
+ },
15
52
  "./tokens": "./src/tokens/index.css",
16
53
  "./tokens/colors": "./src/tokens/colors.css",
17
54
  "./tokens/spacing": "./src/tokens/spacing.css",
@@ -41,7 +41,7 @@
41
41
  });
42
42
  </script>
43
43
 
44
- <div class="jera-accordion {className}" role="region">
44
+ <div class="jera-accordion {className}">
45
45
  {@render children?.()}
46
46
  </div>
47
47
 
@@ -17,6 +17,12 @@
17
17
  Content here
18
18
  </AccordionItem>
19
19
 
20
+ @example Custom indicator icon
21
+ <AccordionItem title="Details">
22
+ {#snippet indicator(open)}<Plus size={14} class={open ? 'rotate-45' : ''} />{/snippet}
23
+ Content here
24
+ </AccordionItem>
25
+
20
26
  @example With leading/trailing snippets
21
27
  <AccordionItem title="Infrastructure">
22
28
  {#snippet leading()}<Activity size={14} />{/snippet}
@@ -37,8 +43,10 @@
37
43
  badge = null,
38
44
  leading,
39
45
  trailing,
46
+ indicator,
40
47
  children,
41
- class: className = ''
48
+ class: className = '',
49
+ ...rest
42
50
  } = $props();
43
51
 
44
52
  const accordion = getContext('accordion');
@@ -63,14 +71,15 @@
63
71
  class="accordion-item {className}"
64
72
  class:accordion-item-solo={!inGroup}
65
73
  class:accordion-item-disabled={disabled}
74
+ {...rest}
66
75
  >
67
76
  <button
68
77
  type="button"
78
+ id="trigger-{itemId}"
69
79
  class="accordion-trigger"
70
80
  class:accordion-trigger-open={isOpen}
71
81
  aria-expanded={isOpen}
72
82
  aria-controls="content-{itemId}"
73
- aria-disabled={disabled || undefined}
74
83
  {disabled}
75
84
  onclick={handleClick}
76
85
  >
@@ -80,20 +89,24 @@
80
89
  <span class="accordion-badge">{badge}</span>
81
90
  {/if}
82
91
  {#if trailing}{@render trailing()}{/if}
83
- <svg
84
- class="accordion-chevron"
85
- class:accordion-chevron-open={isOpen}
86
- width="14"
87
- height="14"
88
- viewBox="0 0 24 24"
89
- fill="none"
90
- stroke="currentColor"
91
- stroke-width="2"
92
- stroke-linecap="round"
93
- stroke-linejoin="round"
94
- >
95
- <polyline points="6 9 12 15 18 9"></polyline>
96
- </svg>
92
+ <span class="accordion-indicator" class:accordion-indicator-open={isOpen}>
93
+ {#if indicator}
94
+ {@render indicator(isOpen)}
95
+ {:else}
96
+ <svg
97
+ width="14"
98
+ height="14"
99
+ viewBox="0 0 24 24"
100
+ fill="none"
101
+ stroke="currentColor"
102
+ stroke-width="2"
103
+ stroke-linecap="round"
104
+ stroke-linejoin="round"
105
+ >
106
+ <polyline points="6 9 12 15 18 9"></polyline>
107
+ </svg>
108
+ {/if}
109
+ </span>
97
110
  </button>
98
111
 
99
112
  {#if isOpen}
@@ -184,23 +197,26 @@
184
197
  border-radius: 9999px;
185
198
  }
186
199
 
187
- /* Chevron */
188
- .accordion-chevron {
200
+ /* Indicator (chevron wrapper) */
201
+ .accordion-indicator {
202
+ display: flex;
203
+ align-items: center;
204
+ justify-content: center;
189
205
  flex-shrink: 0;
190
206
  color: var(--color-base05);
191
207
  transition: transform 0.2s ease;
192
208
  }
193
209
 
194
- .accordion-trigger:hover:not(:disabled) .accordion-chevron {
210
+ .accordion-trigger:hover:not(:disabled) .accordion-indicator {
195
211
  color: var(--color-base06);
196
212
  transform: scale(1.125);
197
213
  }
198
214
 
199
- .accordion-chevron-open {
215
+ .accordion-indicator-open {
200
216
  transform: rotate(180deg);
201
217
  }
202
218
 
203
- .accordion-trigger:hover:not(:disabled) .accordion-chevron-open {
219
+ .accordion-trigger:hover:not(:disabled) .accordion-indicator-open {
204
220
  transform: rotate(180deg) scale(1.125);
205
221
  }
206
222
 
@@ -29,10 +29,12 @@
29
29
  import { setContext, onMount } from 'svelte';
30
30
  import { slide, fade } from 'svelte/transition';
31
31
  import { cubicOut } from 'svelte/easing';
32
+ import LeftBarPopover from './LeftBarPopover.svelte';
32
33
 
33
34
  let {
34
35
  collapsed = $bindable(false),
35
36
  persistKey = null,
37
+ popoverMap = {},
36
38
  class: className = '',
37
39
  header,
38
40
  navigation,
@@ -144,6 +146,16 @@
144
146
  {/if}
145
147
  </div>
146
148
 
149
+ <!-- Hover popover — rendered outside sidebar to avoid overflow:hidden + will-change clipping -->
150
+ {#if isCollapsed && hoverPopover.item && popoverMap[hoverPopover.item]}
151
+ <LeftBarPopover
152
+ visible={true}
153
+ position={hoverPopover.position}
154
+ title={hoverPopover.item}
155
+ items={popoverMap[hoverPopover.item]}
156
+ />
157
+ {/if}
158
+
147
159
  <style>
148
160
  .workspace-sidebar {
149
161
  display: flex;
@@ -166,6 +178,11 @@
166
178
  }
167
179
 
168
180
  .main-nav {
181
+ display: flex;
182
+ flex-direction: column;
183
+ gap: 0.375rem;
184
+ flex: 1;
185
+ overflow-y: auto;
169
186
  padding-top: 0;
170
187
  padding-bottom: 0;
171
188
  }
@@ -125,21 +125,21 @@
125
125
  transform: scale(0.98);
126
126
  }
127
127
 
128
- /* Secondary - Gray background, secondary actions */
128
+ /* Secondary - Light tinted, mirrors primary pattern */
129
129
  .secondary {
130
- background-color: color-mix(in srgb, var(--color-base02, #504945) 30%, transparent);
131
- color: var(--color-base06, #ebdbb2);
132
- border: 1px solid var(--color-base03, #665c54);
130
+ background-color: color-mix(in srgb, var(--color-base03, #665c54) 10%, transparent);
131
+ color: var(--color-base05, #d5c4a1);
132
+ border: 1px solid color-mix(in srgb, var(--color-base03, #665c54) 30%, transparent);
133
133
  }
134
134
 
135
135
  .secondary:hover:not(:disabled) {
136
- background-color: color-mix(in srgb, var(--color-base03, #665c54) 40%, transparent);
137
- border-color: var(--color-base03, #665c54);
136
+ background-color: color-mix(in srgb, var(--color-base03, #665c54) 20%, transparent);
137
+ border-color: color-mix(in srgb, var(--color-base03, #665c54) 50%, transparent);
138
138
  }
139
139
 
140
140
  .secondary:active:not(:disabled) {
141
- background-color: color-mix(in srgb, var(--color-base03, #665c54) 50%, transparent);
142
- border-color: var(--color-base04, #7c6f64);
141
+ background-color: color-mix(in srgb, var(--color-base03, #665c54) 30%, transparent);
142
+ border-color: color-mix(in srgb, var(--color-base04, #7c6f64) 60%, transparent);
143
143
  transform: scale(0.98);
144
144
  }
145
145
 
@@ -169,12 +169,12 @@
169
169
  }
170
170
 
171
171
  .ghost:hover:not(:disabled) {
172
- background-color: color-mix(in srgb, var(--color-base02, #504945) 30%, transparent);
172
+ background-color: var(--color-base01, #3c3836);
173
173
  color: var(--color-base06, #ebdbb2);
174
174
  }
175
175
 
176
176
  .ghost:active:not(:disabled) {
177
- background-color: color-mix(in srgb, var(--color-base02, #504945) 40%, transparent);
177
+ background-color: var(--color-base02, #504945);
178
178
  color: var(--color-base06, #ebdbb2);
179
179
  transform: scale(0.98);
180
180
  }
@@ -215,6 +215,42 @@
215
215
  transform: scale(0.98);
216
216
  }
217
217
 
218
+ /* Warning - Yellow/amber accent */
219
+ .warning {
220
+ background-color: color-mix(in srgb, var(--color-base0A, #fabd2f) 10%, transparent);
221
+ color: var(--color-base0A, #fabd2f);
222
+ border: 1px solid color-mix(in srgb, var(--color-base0A, #fabd2f) 40%, transparent);
223
+ }
224
+
225
+ .warning:hover:not(:disabled) {
226
+ background-color: color-mix(in srgb, var(--color-base0A, #fabd2f) 20%, transparent);
227
+ border-color: color-mix(in srgb, var(--color-base0A, #fabd2f) 60%, transparent);
228
+ }
229
+
230
+ .warning:active:not(:disabled) {
231
+ background-color: color-mix(in srgb, var(--color-base0A, #fabd2f) 30%, transparent);
232
+ border-color: color-mix(in srgb, var(--color-base0A, #fabd2f) 80%, transparent);
233
+ transform: scale(0.98);
234
+ }
235
+
236
+ /* Info - Cyan accent */
237
+ .info {
238
+ background-color: color-mix(in srgb, var(--color-base0C, #8ec07c) 10%, transparent);
239
+ color: var(--color-base0C, #8ec07c);
240
+ border: 1px solid color-mix(in srgb, var(--color-base0C, #8ec07c) 40%, transparent);
241
+ }
242
+
243
+ .info:hover:not(:disabled) {
244
+ background-color: color-mix(in srgb, var(--color-base0C, #8ec07c) 20%, transparent);
245
+ border-color: color-mix(in srgb, var(--color-base0C, #8ec07c) 60%, transparent);
246
+ }
247
+
248
+ .info:active:not(:disabled) {
249
+ background-color: color-mix(in srgb, var(--color-base0C, #8ec07c) 30%, transparent);
250
+ border-color: color-mix(in srgb, var(--color-base0C, #8ec07c) 80%, transparent);
251
+ transform: scale(0.98);
252
+ }
253
+
218
254
  /* ============================================
219
255
  SIZES - matches dash.selify.ai Button exactly
220
256
  ============================================ */