lupine.components 1.1.51 → 1.1.53

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 (37) hide show
  1. package/package.json +1 -1
  2. package/src/component-pool/aspect-ratio/aspect-ratio.tsx +2 -2
  3. package/src/component-pool/avatar/avatar.tsx +3 -3
  4. package/src/component-pool/badge/badge.tsx +2 -2
  5. package/src/component-pool/breadcrumbs/breadcrumbs.tsx +2 -2
  6. package/src/component-pool/card/card.tsx +2 -2
  7. package/src/component-pool/carousel/carousel.tsx +2 -2
  8. package/src/component-pool/cascader/cascader.tsx +2 -2
  9. package/src/component-pool/charts/gauge-chart.tsx +3 -2
  10. package/src/component-pool/charts/pie-chart.tsx +3 -3
  11. package/src/component-pool/charts/radar-chart.tsx +11 -11
  12. package/src/component-pool/charts/scatter-chart.tsx +4 -4
  13. package/src/component-pool/copy-button/copy-button.tsx +2 -2
  14. package/src/component-pool/date-picker/date-picker.tsx +4 -4
  15. package/src/component-pool/floating-icon-menu/floating-icon-menu.tsx +3 -2
  16. package/src/component-pool/map-wrapper/map-wrapper.tsx +3 -4
  17. package/src/component-pool/radial-progress/radial-progress.tsx +2 -2
  18. package/src/component-pool/range/gauge.tsx +2 -2
  19. package/src/component-pool/range/range.tsx +320 -60
  20. package/src/component-pool/search-input/search-input.tsx +2 -2
  21. package/src/component-pool/skeleton/skeleton-card.tsx +2 -2
  22. package/src/component-pool/skeleton/skeleton.tsx +2 -2
  23. package/src/component-pool/tag-input/tag-input.tsx +3 -8
  24. package/src/component-pool/time-picker/time-picker.tsx +3 -3
  25. package/src/component-pool/timeline/timeline.tsx +2 -2
  26. package/src/component-pool/tooltip/tooltip.tsx +2 -2
  27. package/src/components/meta-data.tsx +1 -2
  28. package/src/components/meta-description.tsx +1 -2
  29. package/src/components/popup-menu.tsx +3 -3
  30. package/src/components/redirect.tsx +3 -3
  31. package/src/components/tabs.tsx +2 -2
  32. package/src/demo/demo-render-page.tsx +3 -1
  33. package/src/demo/mock/side-menu-mock.tsx +55 -58
  34. package/src/lib/button-async-lock.tsx +43 -0
  35. package/src/lib/index.ts +1 -1
  36. package/src/styles/dark-themes.ts +2 -2
  37. package/src/lib/encode-html.ts +0 -25
@@ -18,8 +18,12 @@ export type RangeProps = {
18
18
  tickStep?: number;
19
19
  vertical?: boolean;
20
20
  range?: boolean;
21
+ snapThresholdPercent?: number; // threshold in % to snap to tick, <=0 disables snapping (default 5%)
21
22
  onChange?: (val: number | [number, number]) => void;
22
23
  hook?: RangeHookProps;
24
+ trackColor?: string;
25
+ fillColor?: string;
26
+ showButtons?: boolean;
23
27
  };
24
28
 
25
29
  // 1. Define Static CSS completely decoupled from Reactivity (isVertical)
@@ -35,7 +39,6 @@ const rangeCss: CssProps = {
35
39
  padding: 'var(--space-m, 8px) 0',
36
40
  width: '100%',
37
41
  height: 'auto',
38
- minWidth: '100%',
39
42
  minHeight: '40px',
40
43
  },
41
44
  '&.vertical': {
@@ -61,15 +64,17 @@ const rangeCss: CssProps = {
61
64
  '&.horizontal .&-wrapper': {
62
65
  width: '100%',
63
66
  height: '20px',
67
+ flex: 1,
64
68
  },
65
69
  '&.vertical .&-wrapper': {
66
70
  width: '20px',
67
71
  height: '100%',
72
+ flex: 1,
68
73
  },
69
74
 
70
75
  '.&-track': {
71
76
  position: 'relative',
72
- backgroundColor: 'var(--secondary-bg-color, #eee)',
77
+ backgroundColor: 'var(--range-track-color, var(--scrollbar-bg, #eee))',
73
78
  borderRadius: '999px',
74
79
  },
75
80
  '&.horizontal .&-track': {
@@ -83,7 +88,7 @@ const rangeCss: CssProps = {
83
88
 
84
89
  '.&-fill': {
85
90
  position: 'absolute',
86
- backgroundColor: 'var(--primary-accent-color, #0a74c9)',
91
+ backgroundColor: 'var(--range-fill-color, var(--primary-accent-color, #0a74c9))',
87
92
  borderRadius: '999px',
88
93
  },
89
94
  '&.horizontal .&-fill': {
@@ -132,7 +137,7 @@ const rangeCss: CssProps = {
132
137
  width: '20px',
133
138
  height: '20px',
134
139
  backgroundColor: '#fff',
135
- border: '2px solid var(--primary-accent-color, #0a74c9)',
140
+ border: '2px solid var(--range-fill-color, var(--primary-accent-color, #0a74c9))',
136
141
  borderRadius: '50%',
137
142
  cursor: 'pointer',
138
143
  boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
@@ -149,7 +154,7 @@ const rangeCss: CssProps = {
149
154
  width: '20px',
150
155
  height: '20px',
151
156
  backgroundColor: '#fff',
152
- border: '2px solid var(--primary-accent-color, #0a74c9)',
157
+ border: '2px solid var(--range-fill-color, var(--primary-accent-color, #0a74c9))',
153
158
  borderRadius: '50%',
154
159
  cursor: 'pointer',
155
160
  boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
@@ -158,30 +163,24 @@ const rangeCss: CssProps = {
158
163
 
159
164
  '.&-ticks': {
160
165
  position: 'absolute',
161
- display: 'flex',
162
- justifyContent: 'space-between',
163
166
  pointerEvents: 'none',
164
167
  fontSize: '12px',
165
168
  color: 'var(--secondary-color, #818181)',
166
169
  },
167
170
  '&.horizontal .&-ticks': {
168
- top: '50%',
171
+ top: 'calc(50% + 4px)',
169
172
  bottom: 'auto',
170
173
  left: 0,
171
174
  right: 0,
172
- marginTop: '4px',
173
- marginLeft: '4px',
174
- flexDirection: 'row',
175
+ marginTop: 0,
175
176
  height: 'auto',
176
177
  },
177
178
  '&.vertical .&-ticks': {
178
179
  top: 0,
179
180
  bottom: 0,
180
- left: '20%',
181
+ left: 'calc(50% + 4px)',
181
182
  right: 'auto',
182
- marginLeft: '8px',
183
- marginTop: 0,
184
- flexDirection: 'column-reverse',
183
+ marginLeft: 0,
185
184
  height: '100%',
186
185
  },
187
186
 
@@ -211,6 +210,64 @@ const rangeCss: CssProps = {
211
210
  marginBottom: 0,
212
211
  marginRight: '4px',
213
212
  },
213
+
214
+ '.&-inner-container': {
215
+ display: 'flex',
216
+ width: '100%',
217
+ height: '100%',
218
+ },
219
+ '&.horizontal .&-inner-container': {
220
+ flexDirection: 'row',
221
+ alignItems: 'center',
222
+ },
223
+ '&.vertical .&-inner-container': {
224
+ flexDirection: 'column',
225
+ alignItems: 'center',
226
+ },
227
+
228
+ '&.horizontal .&-buttons': {
229
+ display: 'flex',
230
+ flexDirection: 'row',
231
+ alignItems: 'center',
232
+ gap: '6px',
233
+ marginLeft: '10px',
234
+ },
235
+ '&.vertical .&-buttons': {
236
+ display: 'flex',
237
+ flexDirection: 'column',
238
+ alignItems: 'center',
239
+ gap: '6px',
240
+ marginTop: '10px',
241
+ },
242
+ '.&-btn': {
243
+ display: 'flex',
244
+ alignItems: 'center',
245
+ justifyContent: 'center',
246
+ width: '24px',
247
+ height: '24px',
248
+ borderRadius: '50%',
249
+ border: '2px solid var(--range-fill-color, var(--primary-accent-color, #0a74c9))',
250
+ backgroundColor: 'var(--secondary-bg-color, #1c1c1c)',
251
+ color: 'var(--primary-color, #fff)',
252
+ fontSize: '16px',
253
+ fontFamily: 'monospace',
254
+ fontWeight: 'bold',
255
+ cursor: 'pointer',
256
+ padding: 0,
257
+ margin: 0,
258
+ userSelect: 'none',
259
+ transition: 'background-color 0.2s, transform 0.1s',
260
+ lineHeight: '1',
261
+ pointerEvents: 'auto',
262
+ },
263
+ '.&-btn:hover': {
264
+ backgroundColor: 'var(--range-fill-color, var(--primary-accent-color, #0a74c9))',
265
+ color: '#fff',
266
+ transform: 'scale(1.1)',
267
+ },
268
+ '.&-btn:active': {
269
+ transform: 'scale(0.95)',
270
+ },
214
271
  };
215
272
 
216
273
  export const Range = (props: RangeProps) => {
@@ -220,6 +277,10 @@ export const Range = (props: RangeProps) => {
220
277
  const isRangeMode = !!props.range;
221
278
  const isVertical = !!props.vertical;
222
279
 
280
+ const customStyle: any = { ...props.style };
281
+ if (props.trackColor) customStyle['--range-track-color'] = props.trackColor;
282
+ if (props.fillColor) customStyle['--range-fill-color'] = props.fillColor;
283
+
223
284
  // Evaluate the immutable hash exact ONCE for all range implementations.
224
285
  const globalCssId = getGlobalStylesId(rangeCss);
225
286
  // Bind the global style ID ensuring it's in the CSS tree across instances
@@ -247,6 +308,25 @@ export const Range = (props: RangeProps) => {
247
308
  let currentVal1 = val1;
248
309
  let currentVal2 = val2;
249
310
 
311
+ const adjustByStep = (direction: -1 | 1) => {
312
+ if (props.disabled) return;
313
+ if (isRangeMode) {
314
+ let newVal = currentVal1 + direction * step;
315
+ newVal = Math.max(min, Math.min(currentVal2, newVal));
316
+ currentVal1 = newVal;
317
+ const inputMin = ref.$('.input-min') as HTMLInputElement;
318
+ if (inputMin) inputMin.value = currentVal1.toString();
319
+ } else {
320
+ let newVal = currentVal1 + direction * step;
321
+ newVal = Math.max(min, Math.min(max, newVal));
322
+ currentVal1 = newVal;
323
+ const inputSingle = ref.$('.input-single') as HTMLInputElement;
324
+ if (inputSingle) inputSingle.value = currentVal1.toString();
325
+ }
326
+ updateVisuals();
327
+ handleChange();
328
+ };
329
+
250
330
  const updateVisuals = () => {
251
331
  const fill = ref.$('.&-fill') as HTMLElement;
252
332
  if (!fill) return;
@@ -276,8 +356,124 @@ export const Range = (props: RangeProps) => {
276
356
  }
277
357
  };
278
358
 
359
+ let snapThresholdPercent = props.snapThresholdPercent;
360
+ if (snapThresholdPercent === undefined) {
361
+ const tStep = props.tickStep || max - min;
362
+ const tStepPercent = (tStep / (max - min)) * 100;
363
+ snapThresholdPercent = Math.min(5, tStepPercent * 0.1);
364
+ }
365
+
366
+ let animRef = 0;
367
+ const animateToValue = (targetVal: number) => {
368
+ cancelAnimationFrame(animRef);
369
+
370
+ let isThumb2 = false;
371
+ let startVal = currentVal1;
372
+ if (isRangeMode) {
373
+ if (Math.abs(targetVal - currentVal2) < Math.abs(targetVal - currentVal1)) {
374
+ isThumb2 = true;
375
+ startVal = currentVal2;
376
+ }
377
+ }
378
+
379
+ const startTime = performance.now();
380
+ const duration = 200; // 200ms animation
381
+
382
+ const stepAnim = (time: number) => {
383
+ const elapsed = time - startTime;
384
+ let progress = elapsed / duration;
385
+ if (progress > 1) progress = 1;
386
+
387
+ // easeOutQuad
388
+ const eased = progress * (2 - progress);
389
+ const current = startVal + (targetVal - startVal) * eased;
390
+
391
+ if (isRangeMode) {
392
+ if (isThumb2) {
393
+ currentVal2 = current;
394
+ const inputMax = ref.$('.input-max') as HTMLInputElement;
395
+ if (inputMax) inputMax.value = currentVal2.toString();
396
+ } else {
397
+ currentVal1 = current;
398
+ const inputMin = ref.$('.input-min') as HTMLInputElement;
399
+ if (inputMin) inputMin.value = currentVal1.toString();
400
+ }
401
+ } else {
402
+ currentVal1 = current;
403
+ const inputSingle = ref.$('.input-single') as HTMLInputElement;
404
+ if (inputSingle) inputSingle.value = currentVal1.toString();
405
+ }
406
+
407
+ updateVisuals();
408
+
409
+ if (progress < 1) {
410
+ animRef = requestAnimationFrame(stepAnim);
411
+ } else {
412
+ handleChange();
413
+ }
414
+ };
415
+
416
+ animRef = requestAnimationFrame(stepAnim);
417
+ };
418
+
419
+ const handleContainerClick = (e: any) => {
420
+ if (props.disabled) return;
421
+ if (e.target && e.target.tagName === 'INPUT') return;
422
+
423
+ const wrapper = ref.$('.&-wrapper') as HTMLElement;
424
+ if (!wrapper) return;
425
+ const rect = wrapper.getBoundingClientRect();
426
+
427
+ let clientX = e.clientX;
428
+ let clientY = e.clientY;
429
+ if (e.type === 'touchstart') {
430
+ const touch = (e as unknown as TouchEvent).touches[0];
431
+ if (touch) {
432
+ clientX = touch.clientX;
433
+ clientY = touch.clientY;
434
+ }
435
+ }
436
+
437
+ let percent = 0;
438
+ if (isVertical) {
439
+ const y = clientY - rect.top;
440
+ percent = 1 - y / rect.height;
441
+ } else {
442
+ const x = clientX - rect.left;
443
+ percent = x / rect.width;
444
+ }
445
+ percent = Math.max(0, Math.min(1, percent));
446
+
447
+ let targetVal = min + (max - min) * percent;
448
+ targetVal = Math.round((targetVal - min) / step) * step + min;
449
+
450
+ if (snapThresholdPercent > 0 && (props.showTicks || props.showTickLabels)) {
451
+ const tStep = props.tickStep || max - min;
452
+ const nearestTick = Math.round((targetVal - min) / tStep) * tStep + min;
453
+ const threshold = (max - min) * (snapThresholdPercent / 100);
454
+ if (Math.abs(targetVal - nearestTick) <= threshold) {
455
+ targetVal = nearestTick;
456
+ }
457
+ }
458
+
459
+ targetVal = Math.max(min, Math.min(max, targetVal));
460
+ animateToValue(targetVal);
461
+ };
462
+
279
463
  const handleInput = (e: Event, isThumb2: boolean) => {
280
- const val = parseFloat((e.target as HTMLInputElement).value);
464
+ let val = parseFloat((e.target as HTMLInputElement).value);
465
+
466
+ // Magnetic snapping
467
+ if (snapThresholdPercent > 0 && (props.showTicks || props.showTickLabels)) {
468
+ const tStep = props.tickStep || max - min;
469
+ const nearestTick = Math.round((val - min) / tStep) * tStep + min;
470
+ const threshold = (max - min) * (snapThresholdPercent / 100);
471
+ if (Math.abs(val - nearestTick) <= threshold) {
472
+ val = nearestTick;
473
+ (e.target as HTMLInputElement).value = val.toString();
474
+ }
475
+ }
476
+
281
477
  if (isRangeMode) {
282
478
  if (isThumb2) {
283
479
  currentVal2 = Math.max(val, currentVal1);
@@ -296,6 +492,7 @@ export const Range = (props: RangeProps) => {
296
492
  currentVal1 = val;
297
493
  }
298
494
  updateVisuals();
495
+ handleChange(); // Ensure parent receives continuous updates during drag
299
496
  };
300
497
 
301
498
  const handleChange = () => {
@@ -328,7 +525,7 @@ export const Range = (props: RangeProps) => {
328
525
  }
329
526
 
330
527
  const ref: RefProps & { onUnload?: (el: Element) => Promise<void> | void } = {
331
- globalCssId,
528
+ referToCssId: globalCssId,
332
529
  onLoad: async () => {
333
530
  if (isVertical) {
334
531
  const wrapper = ref.$('.&-wrapper') as HTMLElement;
@@ -366,22 +563,49 @@ export const Range = (props: RangeProps) => {
366
563
 
367
564
  return (
368
565
  <div
369
- class={['&-container', props.class, props.disabled ? 'disabled' : '', isVertical ? 'vertical' : 'horizontal']
566
+ class={[globalCssId, '&-container', props.class, props.disabled ? 'disabled' : '', isVertical ? 'vertical' : 'horizontal']
370
567
  .join(' ')
371
568
  .trim()}
372
569
  ref={ref}
373
- css={props.style}
570
+ css={customStyle}
571
+ onPointerDown={handleContainerClick}
572
+ onTouchStart={handleContainerClick}
374
573
  >
375
- <div class='&-wrapper'>
376
- <div class='&-track'>
377
- <div class='&-fill'></div>
378
- </div>
574
+ <div class='&-inner-container'>
575
+ <div class='&-wrapper'>
576
+ <div class='&-track'>
577
+ <div class='&-fill'></div>
578
+ </div>
379
579
 
380
- {isRangeMode ? (
381
- <>
580
+ {isRangeMode ? (
581
+ <>
582
+ <input
583
+ type='range'
584
+ class='&-input input-min'
585
+ min={min}
586
+ max={max}
587
+ step={step}
588
+ value={val1}
589
+ onInput={(e) => handleInput(e, false)}
590
+ onChange={handleChange}
591
+ disabled={props.disabled}
592
+ />
593
+ <input
594
+ type='range'
595
+ class='&-input input-max'
596
+ min={min}
597
+ max={max}
598
+ step={step}
599
+ value={val2}
600
+ onInput={(e) => handleInput(e, true)}
601
+ onChange={handleChange}
602
+ disabled={props.disabled}
603
+ />
604
+ </>
605
+ ) : (
382
606
  <input
383
607
  type='range'
384
- class='&-input input-min'
608
+ class='&-input input-single'
385
609
  min={min}
386
610
  max={max}
387
611
  step={step}
@@ -390,43 +614,79 @@ export const Range = (props: RangeProps) => {
390
614
  onChange={handleChange}
391
615
  disabled={props.disabled}
392
616
  />
393
- <input
394
- type='range'
395
- class='&-input input-max'
396
- min={min}
397
- max={max}
398
- step={step}
399
- value={val2}
400
- onInput={(e) => handleInput(e, true)}
401
- onChange={handleChange}
402
- disabled={props.disabled}
403
- />
404
- </>
405
- ) : (
406
- <input
407
- type='range'
408
- class='&-input input-single'
409
- min={min}
410
- max={max}
411
- step={step}
412
- value={val1}
413
- onInput={(e) => handleInput(e, false)}
414
- onChange={handleChange}
415
- disabled={props.disabled}
416
- />
417
- )}
418
- </div>
617
+ )}
618
+
619
+ {(props.showTicks || props.showTickLabels) && (
620
+ <div class='&-ticks'>
621
+ {ticks.map((t) => {
622
+ const percent = ((t - min) / (max - min)) * 100;
623
+ const offsetPx = 10 - (percent / 100) * 20;
624
+ const style = isVertical
625
+ ? { position: 'absolute' as any, bottom: `calc(${percent}% + ${offsetPx}px)`, transform: 'translateY(50%)' }
626
+ : { position: 'absolute' as any, left: `calc(${percent}% + ${offsetPx}px)`, top: '0', transform: 'translateX(-50%)' };
419
627
 
420
- {(props.showTicks || props.showTickLabels) && (
421
- <div class='&-ticks'>
422
- {ticks.map((t) => (
423
- <div class='&-tick'>
424
- {props.showTicks && <div class='&-tick-mark'></div>}
425
- {props.showTickLabels && <span>{t}</span>}
628
+ return (
629
+ <div class='&-tick' style={style}>
630
+ {props.showTicks && <div class='&-tick-mark'></div>}
631
+ {props.showTickLabels && (
632
+ <span
633
+ style={{ pointerEvents: 'auto', cursor: 'pointer' }}
634
+ onPointerDown={(e: any) => {
635
+ e.stopPropagation();
636
+ animateToValue(t);
637
+ }}
638
+ onTouchStart={(e: any) => {
639
+ e.stopPropagation();
640
+ animateToValue(t);
641
+ }}
642
+ >
643
+ {t}
644
+ </span>
645
+ )}
646
+ </div>
647
+ );
648
+ })}
426
649
  </div>
427
- ))}
650
+ )}
428
651
  </div>
429
- )}
652
+
653
+ {props.showButtons && (
654
+ <div class='&-buttons'>
655
+ <button
656
+ class='&-btn &-btn-minus'
657
+ onPointerDown={(e: any) => {
658
+ e.stopPropagation();
659
+ adjustByStep(-1);
660
+ }}
661
+ onTouchStart={(e: any) => {
662
+ e.stopPropagation();
663
+ adjustByStep(-1);
664
+ }}
665
+ onClick={(e: any) => {
666
+ e.stopPropagation();
667
+ }}
668
+ >
669
+ -
670
+ </button>
671
+ <button
672
+ class='&-btn &-btn-plus'
673
+ onPointerDown={(e: any) => {
674
+ e.stopPropagation();
675
+ adjustByStep(1);
676
+ }}
677
+ onTouchStart={(e: any) => {
678
+ e.stopPropagation();
679
+ adjustByStep(1);
680
+ }}
681
+ onClick={(e: any) => {
682
+ e.stopPropagation();
683
+ }}
684
+ >
685
+ +
686
+ </button>
687
+ </div>
688
+ )}
689
+ </div>
430
690
  </div>
431
691
  );
432
692
  };
@@ -69,7 +69,7 @@ export const SearchInput = (props: InputWithClearProps) => {
69
69
  bindGlobalStyle(globalCssId, css);
70
70
 
71
71
  const ref: RefProps = {
72
- globalCssId,
72
+ referToCssId: globalCssId,
73
73
  };
74
74
 
75
75
  const onSearch = () => {
@@ -97,7 +97,7 @@ export const SearchInput = (props: InputWithClearProps) => {
97
97
  }
98
98
 
99
99
  return (
100
- <div ref={ref} class={['search-input', props.class].join(' ').trim()}>
100
+ <div ref={ref} class={[globalCssId, 'search-input', props.class].join(' ').trim()}>
101
101
  <input
102
102
  type='text'
103
103
  maxLength={30}
@@ -43,7 +43,7 @@ export const SkeletonCard = (props: SkeletonCardProps) => {
43
43
  const contentRef: RefProps = {};
44
44
 
45
45
  const ref: RefProps = {
46
- globalCssId,
46
+ referToCssId: globalCssId,
47
47
  onLoad: async () => {
48
48
  const container = ref.current as HTMLElement;
49
49
 
@@ -106,7 +106,7 @@ export const SkeletonCard = (props: SkeletonCardProps) => {
106
106
 
107
107
  // Avatar size is fixed to 48px to represent a typical user profile
108
108
  return (
109
- <div class={['&-container', props.class].join(' ').trim()} ref={ref} css={mergedStyle} aria-hidden='true'>
109
+ <div class={[globalCssId, '&-container', props.class].join(' ').trim()} ref={ref} css={mergedStyle} aria-hidden='true'>
110
110
  <Skeleton width='48px' height='48px' circle={true} animated={animated} />
111
111
  <div class='&-content' ref={contentRef}></div>
112
112
  </div>
@@ -34,7 +34,7 @@ export const Skeleton = (props: SkeletonProps) => {
34
34
  bindGlobalStyle(globalCssId, css);
35
35
 
36
36
  const ref: RefProps = {
37
- globalCssId,
37
+ referToCssId: globalCssId,
38
38
  };
39
39
 
40
40
  const isAnimated = props.animated !== false; // defaults to true
@@ -50,7 +50,7 @@ export const Skeleton = (props: SkeletonProps) => {
50
50
 
51
51
  return (
52
52
  <div
53
- class={['&-container', isAnimated ? 'is-animated' : '', isCircle ? 'is-circle' : '', props.class]
53
+ class={[globalCssId, '&-container', isAnimated ? 'is-animated' : '', isCircle ? 'is-circle' : '', props.class]
54
54
  .join(' ')
55
55
  .trim()}
56
56
  ref={ref}
@@ -89,7 +89,7 @@ export const TagInput = ({
89
89
  bindGlobalStyle(globalCssId, tagInputCss);
90
90
 
91
91
  const ref: RefProps = {
92
- globalCssId,
92
+ referToCssId: globalCssId,
93
93
  };
94
94
 
95
95
  let currentSelection = [...selectedIndices];
@@ -97,7 +97,7 @@ export const TagInput = ({
97
97
  const renderTags = () => {
98
98
  // pass globalCssId for & in classname
99
99
  const tempRef: RefProps = {
100
- globalCssId,
100
+ referToCssId: globalCssId,
101
101
  };
102
102
  if (currentSelection.length === 0) {
103
103
  return (
@@ -158,13 +158,8 @@ export const TagInput = ({
158
158
  };
159
159
 
160
160
  const dom = new HtmlVar(renderTags());
161
-
162
- // Combine native classes, framework namespace (from globalCssId), and optional extra classes
163
- let finalClass = cls || '';
164
- if (disabled) finalClass += ' disabled';
165
-
166
161
  return (
167
- <div ref={ref} css={extraCss} class={finalClass} onClick={openSelector}>
162
+ <div ref={ref} css={extraCss} class={[globalCssId, cls, disabled ? 'disabled' : ''].filter(Boolean).join(' ')} onClick={openSelector}>
168
163
  {dom.node}
169
164
  </div>
170
165
  );
@@ -133,7 +133,7 @@ export const TimePicker = (props: TimePickerProps) => {
133
133
  const globalCssId = getGlobalStylesId(timePickerCss);
134
134
  bindGlobalStyle(globalCssId, timePickerCss);
135
135
 
136
- const ref: RefProps = { globalCssId };
136
+ const ref: RefProps = { referToCssId: globalCssId };
137
137
  let currentValue = props.value || '';
138
138
 
139
139
  const parseValue = (val: string) => {
@@ -189,7 +189,7 @@ export const TimePicker = (props: TimePickerProps) => {
189
189
  const seconds = Array.from({ length: 60 }, (_, i) => i);
190
190
 
191
191
  const panelRef: RefProps = {
192
- globalCssId,
192
+ referToCssId: globalCssId,
193
193
  onLoad: async () => {
194
194
  setTimeout(highlightSelection, 10);
195
195
  },
@@ -285,7 +285,7 @@ export const TimePicker = (props: TimePickerProps) => {
285
285
  };
286
286
 
287
287
  return (
288
- <div class='&-container' css={props.style} ref={ref}>
288
+ <div class={[globalCssId, '&-container'].join(' ')} css={props.style} ref={ref}>
289
289
  <input
290
290
  class={['&-input', props.className || 'input-base'].join(' ')}
291
291
  placeholder={props.placeholder || 'Select time'}
@@ -96,7 +96,7 @@ export const Timeline = (props: TimelineProps) => {
96
96
  bindGlobalStyle(globalCssId, timelineCss);
97
97
 
98
98
  const ref: RefProps = {
99
- globalCssId,
99
+ referToCssId: globalCssId,
100
100
  };
101
101
 
102
102
  const lineColor = props.lineColor || 'var(--secondary-border-color, #ccc)';
@@ -108,7 +108,7 @@ export const Timeline = (props: TimelineProps) => {
108
108
  };
109
109
 
110
110
  return (
111
- <div class={['&-container', props.class].join(' ').trim()} ref={ref} css={containerStyle}>
111
+ <div class={[globalCssId, '&-container', props.class].join(' ').trim()} ref={ref} css={containerStyle}>
112
112
  <div class='&-line' style={{ backgroundColor: lineColor }}></div>
113
113
 
114
114
  {(props.items || []).map((item, index) => {
@@ -222,14 +222,14 @@ const TooltipContent = (props: {
222
222
  bindGlobalStyle(globalCssId, tooltipCss);
223
223
 
224
224
  const ref: RefProps = {
225
- globalCssId,
225
+ referToCssId: globalCssId,
226
226
  onLoad: async () => {
227
227
  props.onRef(ref);
228
228
  },
229
229
  };
230
230
 
231
231
  return (
232
- <div class={['&-container', props.position].join(' ')} ref={ref}>
232
+ <div class={[globalCssId, '&-container', props.position].join(' ')} ref={ref}>
233
233
  <div class='&-box'>
234
234
  {props.content}
235
235
  {props.showArrow && <div class='&-arrow' />}
@@ -1,6 +1,5 @@
1
1
  // import { bindPageResetEvent } from '../core/page-reset-events';
2
- import { addMetaDataTags } from 'lupine.web';
3
- import { encodeHtml } from '../lib';
2
+ import { addMetaDataTags, encodeHtml } from 'lupine.web';
4
3
  type NameMeta = { name: string; content: string };
5
4
  type PropertyMeta = { property: string; content: string };
6
5
  type HttpEquivMeta = { httpEquiv: string; content: string };
@@ -1,7 +1,6 @@
1
1
  // import { bindPageResetEvent } from '../core/page-reset-events';
2
2
 
3
- import { addMetaDataTags } from 'lupine.web';
4
- import { encodeHtml } from '../lib';
3
+ import { addMetaDataTags, encodeHtml } from 'lupine.web';
5
4
 
6
5
  export const MetaDescription = ({ children }: { children: string }) => {
7
6
  addMetaDataTags('name:description', `<meta name="description" content="${encodeHtml(children)}">`);