noph-ui 0.6.12 → 0.7.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 CHANGED
@@ -65,7 +65,7 @@ Beta (No breaking changes expected)
65
65
  - Ripple
66
66
  - Segmented buttons
67
67
  - Snackbar
68
- - Text fields (Textarea Docs missing)
68
+ - Text fields (Textarea + Docs missing)
69
69
 
70
70
  In progress (Breaking changes expected)
71
71
 
@@ -74,11 +74,10 @@ In progress (Breaking changes expected)
74
74
  - Menus (Positioning missing + Docs missing)
75
75
  - Navigation Rail (Badge is missing)
76
76
  - Tooltips (Positioning missing)
77
+ - Select
77
78
 
78
79
  Pending
79
80
 
80
- - Dialogs
81
- - Select
82
81
  - Sliders
83
82
  - Switch
84
83
  - Tabs
@@ -54,7 +54,11 @@
54
54
  aria-label={title || attributes['aria-label']}
55
55
  {disabled}
56
56
  bind:this={element}
57
- class="np-button {variant}{disabled ? '-disabled disabled' : ' enabled'} {attributes.class}"
57
+ class={[
58
+ 'np-button',
59
+ disabled ? `${variant}-disabled disabled` : `${variant} enabled`,
60
+ attributes.class,
61
+ ]}
58
62
  >
59
63
  {@render content()}
60
64
  </button>
@@ -64,7 +68,7 @@
64
68
  aria-describedby={title ? tooltipId : attributes['aria-describedby']}
65
69
  aria-label={title || attributes['aria-label']}
66
70
  bind:this={element}
67
- class="np-button enabled {variant} {attributes.class}"
71
+ class={['np-button', 'enabled', variant, attributes.class]}
68
72
  >
69
73
  {@render content()}
70
74
  </a>
@@ -57,13 +57,13 @@
57
57
  {...attributes as HTMLButtonAttributes}
58
58
  {disabled}
59
59
  bind:this={element}
60
- class="np-icon-button {variant}{disabled ? '-disabled disabled' : ' enabled'}{toggle
61
- ? ' toggle '
62
- : ''}{selectedState
63
- ? (variant === 'outlined' || variant === 'text') && !toggle
64
- ? ''
65
- : ' selected'
66
- : ''} {attributes.class}"
60
+ class={[
61
+ 'np-icon-button',
62
+ disabled ? `${variant}-disabled disabled` : `${variant} enabled`,
63
+ toggle && 'toggle',
64
+ selectedState && ((variant !== 'outlined' && variant !== 'text') || toggle) && 'selected',
65
+ attributes.class,
66
+ ]}
67
67
  >
68
68
  {@render content()}
69
69
  </button>
@@ -73,11 +73,12 @@
73
73
  aria-describedby={title ? tooltipId : undefined}
74
74
  aria-label={title}
75
75
  bind:this={element}
76
- class="np-icon-button enabled {variant} {selectedState
77
- ? (variant === 'outlined' || variant === 'text') && !toggle
78
- ? ''
79
- : ' selected'
80
- : ''} {attributes.class}"
76
+ class={[
77
+ 'np-icon-button',
78
+ variant,
79
+ selectedState && ((variant !== 'outlined' && variant !== 'text') || toggle) && 'selected',
80
+ attributes.class,
81
+ ]}
81
82
  >
82
83
  {@render content()}
83
84
  </a>
@@ -15,7 +15,7 @@
15
15
 
16
16
  <div
17
17
  {...attributes}
18
- class="np-segmented-buttons {attributes.class}"
18
+ class={['np-segmented-buttons', attributes.class]}
19
19
  bind:this={element}
20
20
  style="{attributes.style};grid-template-columns: repeat({options.length}, minmax(max-content, 1fr));"
21
21
  >
@@ -63,21 +63,25 @@
63
63
  {/if}
64
64
  {/snippet}
65
65
 
66
- {#if attributes.type === 'text' || disabled}
66
+ {#if attributes.type === 'text'}
67
67
  <div
68
- {...attributes as HTMLAttributes<HTMLDivElement>}
68
+ {...attributes}
69
69
  bind:this={element}
70
70
  aria-disabled={disabled}
71
- class="np-card-container np-card-{variant}{disabled
72
- ? ' np-card-disabled'
73
- : ''} {attributes.class}"
71
+ class={[
72
+ 'np-card-container',
73
+ `np-card-${variant}`,
74
+ disabled && 'np-card-disabled',
75
+ attributes.class,
76
+ ]}
74
77
  >
75
78
  {@render content()}
76
79
  </div>
77
80
  {:else if attributes.type === 'button'}
78
81
  <button
79
- {...attributes as HTMLButtonAttributes}
82
+ {...attributes}
80
83
  bind:this={element}
84
+ aria-disabled={disabled}
81
85
  onfocusin={() => {
82
86
  focused = true
83
87
  }}
@@ -85,9 +89,12 @@
85
89
  focused = false
86
90
  }}
87
91
  {disabled}
88
- class="np-card-container np-card-{variant}{disabled
89
- ? ' np-card-disabled'
90
- : ''} {attributes.class}"
92
+ class={[
93
+ 'np-card-container',
94
+ `np-card-${variant}`,
95
+ disabled && 'np-card-disabled',
96
+ attributes.class,
97
+ ]}
91
98
  >
92
99
  {@render content()}
93
100
  </button>
@@ -95,15 +102,21 @@
95
102
  <a
96
103
  {...attributes}
97
104
  bind:this={element}
105
+ aria-disabled={disabled}
106
+ tabindex={disabled ? -1 : undefined}
107
+ role="link"
98
108
  onfocusin={() => {
99
109
  focused = true
100
110
  }}
101
111
  onfocusout={() => {
102
112
  focused = false
103
113
  }}
104
- class="np-card-container np-card-{variant}{disabled
105
- ? ' np-card-disabled'
106
- : ''} {attributes.class}"
114
+ class={[
115
+ 'np-card-container',
116
+ `np-card-${variant}`,
117
+ disabled && 'np-card-disabled',
118
+ attributes.class,
119
+ ]}
107
120
  >
108
121
  {@render content()}
109
122
  </a>
@@ -13,12 +13,12 @@
13
13
  <div class="np-container">
14
14
  <label class="np-input-wrapper">
15
15
  <input
16
+ {...attributes}
16
17
  class="np-input"
17
18
  type="checkbox"
18
19
  bind:indeterminate
19
20
  bind:checked
20
21
  aria-checked={indeterminate ? 'mixed' : undefined}
21
- {...attributes}
22
22
  />
23
23
  {#if !attributes.disabled}
24
24
  <Ripple />
@@ -4,13 +4,7 @@
4
4
  let { variant = 'full', ...attributes }: DividerProps = $props()
5
5
  </script>
6
6
 
7
- <template
8
- class:full={variant === 'full'}
9
- class:inset={variant === 'inset'}
10
- class:inset-middle={variant === 'inset-middle'}
11
- role="separator"
12
- {...attributes}
13
- class="divider {attributes.class}"
7
+ <template {...attributes} role="separator" class={['np-divider', variant, attributes.class]}
14
8
  ></template>
15
9
 
16
10
  <style>
@@ -26,7 +20,7 @@
26
20
  .full {
27
21
  width: 100%;
28
22
  }
29
- .divider {
23
+ .np-divider {
30
24
  height: 1px;
31
25
  display: flex;
32
26
  background-color: var(--np-divider-color, var(--np-color-outline-variant));
@@ -35,7 +35,7 @@
35
35
  </div>
36
36
 
37
37
  {#if end}
38
- <div class="np-item-end {selected ? 'selected ' : ''}">
38
+ <div class={['np-item-end', selected && 'selected']}>
39
39
  {@render end()}
40
40
  </div>
41
41
  {/if}
@@ -45,17 +45,17 @@
45
45
  {/snippet}
46
46
 
47
47
  {#if disabled}
48
- <div aria-disabled="true" class="np-item disabled {attributes.class}">
48
+ <div aria-disabled="true" class={['np-item disabled', attributes.class]}>
49
49
  {@render content()}
50
50
  </div>
51
51
  {:else if attributes.variant === 'text' || attributes.variant === undefined}
52
- <div {...attributes} class="{selected ? 'selected ' : ''} np-item {attributes.class}">
52
+ <div {...attributes} class={['np-item', selected && 'selected', attributes.class]}>
53
53
  {@render content()}
54
54
  </div>
55
55
  {:else if attributes.variant === 'button'}
56
56
  <button
57
57
  {...attributes}
58
- class="{selected ? 'selected ' : ''} np-item {attributes.class}"
58
+ class={['np-item', selected && 'selected', attributes.class]}
59
59
  onfocus={() => {
60
60
  focused = true
61
61
  }}
@@ -66,7 +66,7 @@
66
66
  {:else if attributes.variant === 'link'}
67
67
  <a
68
68
  {...attributes}
69
- class="{selected ? 'selected ' : ''} np-item {attributes.class}"
69
+ class={['np-item', selected && 'selected', attributes.class]}
70
70
  onfocus={() => {
71
71
  focused = true
72
72
  }}
@@ -78,12 +78,12 @@
78
78
  />
79
79
 
80
80
  <div
81
+ {...attributes}
81
82
  bind:this={element}
82
83
  bind:clientWidth
83
84
  bind:clientHeight
84
- {...attributes}
85
85
  popover="auto"
86
- class="np-menu {attributes.class}"
86
+ class={['np-menu', attributes.class]}
87
87
  role="menu"
88
88
  >
89
89
  {@render children()}
@@ -101,9 +101,8 @@
101
101
  margin: 0;
102
102
  margin-bottom: 2px;
103
103
  margin-top: 2px;
104
- top: anchor(bottom);
104
+ position-area: bottom;
105
105
  position-try-fallbacks: --menu-top;
106
- justify-self: anchor-center;
107
106
  transition:
108
107
  display 0.2s allow-discrete,
109
108
  opacity 0.2s linear;
@@ -291,9 +291,12 @@
291
291
  <div
292
292
  aria-hidden="true"
293
293
  {...attributes}
294
- class="{pressed ? 'np-ripple-pressed' : ''} {hovered || forceHover
295
- ? 'np-ripple-hovered'
296
- : ''} np-ripple-surface {attributes.class}"
294
+ class={[
295
+ pressed && 'np-ripple-pressed',
296
+ (hovered || forceHover) && 'np-ripple-hovered',
297
+ 'np-ripple-surface',
298
+ attributes.class,
299
+ ]}
297
300
  bind:this={element}
298
301
  ></div>
299
302
 
@@ -0,0 +1,45 @@
1
+ <script lang="ts">
2
+ import Menu from '../menu/Menu.svelte'
3
+ import TextField from '../text-field/TextField.svelte'
4
+
5
+ let { children, value = $bindable() } = $props()
6
+ </script>
7
+
8
+ <select class="custom-select">
9
+ <option>Option 1</option>
10
+ <option>Option 2</option>
11
+ <option>Option 3</option>
12
+ </select>
13
+
14
+ <style>
15
+ .custom-select {
16
+ appearance: none; /* Entfernt standardmäßigen Stil */
17
+ -webkit-appearance: none; /* Für Safari */
18
+ -moz-appearance: none; /* Für Firefox */
19
+ background-color: none;
20
+ border-width: 1px;
21
+ border-style: solid;
22
+ border-color: var(--np-color-outline);
23
+ border-radius: var(--np-shape-corner-extra-small);
24
+ padding: 8px 12px;
25
+ font-size: 16px;
26
+ color: var(--np-color-on-surface);
27
+ cursor: pointer;
28
+ width: 200px;
29
+ position: relative;
30
+ }
31
+
32
+ .custom-select:focus {
33
+ outline: none;
34
+ border-color: var(--np-color-primary);
35
+ border-width: 3px;
36
+ }
37
+
38
+ /* Optional: Ein Pfeil-Icon simulieren */
39
+ .custom-select::after {
40
+ content: '▼';
41
+ position: absolute;
42
+ right: 12px;
43
+ pointer-events: none;
44
+ }
45
+ </style>
@@ -0,0 +1,6 @@
1
+ declare const Select: import("svelte").Component<{
2
+ children: any;
3
+ value?: any;
4
+ }, {}, "value">;
5
+ type Select = ReturnType<typeof Select>;
6
+ export default Select;
@@ -0,0 +1 @@
1
+ export { default as Select } from './Select.svelte';
@@ -0,0 +1 @@
1
+ export { default as Select } from './Select.svelte';
@@ -0,0 +1,6 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ export interface SelectProps extends HTMLAttributes<HTMLDivElement> {
3
+ forceHover?: boolean;
4
+ element?: HTMLDivElement;
5
+ forElement?: HTMLElement;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -46,7 +46,7 @@
46
46
  <div
47
47
  {...attributes}
48
48
  {popover}
49
- class="np-snackbar {attributes.class}"
49
+ class={['np-snackbar', attributes.class]}
50
50
  onbeforetoggle={toggleHandler}
51
51
  bind:this={element}
52
52
  >
@@ -59,9 +59,7 @@
59
59
  })
60
60
  </script>
61
61
 
62
- <!-- svelte-ignore a11y_click_events_have_key_events -->
63
- <!-- svelte-ignore a11y_no_static_element_interactions -->
64
- <span
62
+ <label
65
63
  style={(variant === 'outlined'
66
64
  ? '--top-space:1rem;--bottom-space:1rem;--floating-label-top:-0.5rem;--floating-label-left:-2.25rem;--_focus-outline-width:3px;'
67
65
  : !label?.length
@@ -69,12 +67,6 @@
69
67
  : '') + style}
70
68
  class="text-field"
71
69
  bind:this={element}
72
- onclick={() => {
73
- if (attributes.disabled) {
74
- return
75
- }
76
- textElement?.focus()
77
- }}
78
70
  >
79
71
  <div
80
72
  class="field"
@@ -171,7 +163,7 @@
171
163
  </div>
172
164
  {/if}
173
165
  </div>
174
- </span>
166
+ </label>
175
167
 
176
168
  <style>
177
169
  .active-indicator {
@@ -46,7 +46,7 @@
46
46
 
47
47
  <div
48
48
  {...attributes}
49
- class="tooltip {attributes.class}"
49
+ class={['tooltip', attributes.class]}
50
50
  style="top:{calculateTopPos}px;left:{calculateLeftPos}px;{attributes.style}"
51
51
  role="tooltip"
52
52
  bind:clientWidth
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.6.12",
3
+ "version": "0.7.0",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {
@@ -49,13 +49,13 @@
49
49
  "!dist/**/*.spec.*"
50
50
  ],
51
51
  "peerDependencies": {
52
- "svelte": "^5.0.0"
52
+ "svelte": "^5.16.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@material/material-color-utilities": "^0.3.0",
56
56
  "@playwright/test": "^1.49.1",
57
57
  "@sveltejs/adapter-vercel": "^5.5.2",
58
- "@sveltejs/kit": "^2.13.0",
58
+ "@sveltejs/kit": "^2.15.0",
59
59
  "@sveltejs/package": "^2.3.7",
60
60
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
61
61
  "@types/eslint": "^9.6.1",
@@ -66,10 +66,10 @@
66
66
  "prettier": "^3.4.2",
67
67
  "prettier-plugin-svelte": "^3.3.2",
68
68
  "publint": "^0.2.12",
69
- "svelte": "^5.15.0",
69
+ "svelte": "^5.16.0",
70
70
  "svelte-check": "^4.1.1",
71
71
  "typescript": "^5.7.2",
72
- "typescript-eslint": "^8.18.1",
72
+ "typescript-eslint": "^8.18.2",
73
73
  "vite": "^6.0.5",
74
74
  "vitest": "^2.1.8"
75
75
  },