ps-helix 7.0.0 → 7.0.1
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 +3 -3
- package/TOKENS.md +1 -1
- package/fesm2022/ps-helix.mjs +43 -16
- package/fesm2022/ps-helix.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/styles/themes/dark-auto.css +4 -1
- package/src/lib/styles/themes/dark.css +4 -1
- package/types/ps-helix.d.ts +9 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A comprehensive Angular component library built with Angular 22+ featuring modern design patterns, accessibility-first development, and optimal developer experience.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/ps-helix)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://angular.dev/)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
@@ -108,7 +108,7 @@ After installation, verify that ps-helix is in your `package.json`:
|
|
|
108
108
|
```json
|
|
109
109
|
{
|
|
110
110
|
"dependencies": {
|
|
111
|
-
"ps-helix": "^7.0.
|
|
111
|
+
"ps-helix": "^7.0.1"
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
```
|
|
@@ -1188,7 +1188,7 @@ Copyright (c) 2025 PACK Solutions
|
|
|
1188
1188
|
|
|
1189
1189
|
---
|
|
1190
1190
|
|
|
1191
|
-
**Version**: 7.0.
|
|
1191
|
+
**Version**: 7.0.1
|
|
1192
1192
|
**Built with**: Angular 22.0.0, TypeScript 6.0.0, Phosphor Icons 2.0.3
|
|
1193
1193
|
**Author**: Fabrice PEREZ | Design Engineer at PACK Solutions
|
|
1194
1194
|
**Last Updated**: January 2026
|
package/TOKENS.md
CHANGED
|
@@ -39,7 +39,7 @@ used before 7.0.0 remain available through the opt-in `styles/compat.css`.
|
|
|
39
39
|
| `--psh-text-color-secondary` | `var(--psh-surface-600)` | `rgba(255, 255, 255, 0.75)` |
|
|
40
40
|
| `--psh-text-color-tertiary` | `var(--psh-surface-500)` | `rgba(255, 255, 255, 0.6)` |
|
|
41
41
|
| `--psh-text-color-disabled` | `var(--psh-surface-400)` | `rgba(255, 255, 255, 0.4)` |
|
|
42
|
-
| `--psh-text-on-primary` | `#FFFFFF` | `#
|
|
42
|
+
| `--psh-text-on-primary` | `#FFFFFF` | `#000000` |
|
|
43
43
|
| `--psh-text-on-secondary` | `#FFFFFF` | `#FFFFFF` |
|
|
44
44
|
| `--psh-text-on-success` | `#FFFFFF` | `#000000` |
|
|
45
45
|
| `--psh-text-on-warning` | `#FFFFFF` | `#000000` |
|
package/fesm2022/ps-helix.mjs
CHANGED
|
@@ -214,23 +214,31 @@ class ThemeService {
|
|
|
214
214
|
this.initializeTheme();
|
|
215
215
|
afterNextRender(() => this.applyCustomerTheme());
|
|
216
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Switches theme *and* remembers the choice — the two halves of what a theme toggle
|
|
219
|
+
* means. They used to be split across two methods: `setDarkTheme` wrote `data-theme`
|
|
220
|
+
* without persisting, `updateTheme` persisted without writing `data-theme`. Whichever
|
|
221
|
+
* one a consumer picked, half the job was missing, and the demo's own toggle reverted
|
|
222
|
+
* on every reload.
|
|
223
|
+
*/
|
|
217
224
|
setDarkTheme(isDark) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
this.isDarkThemeSignal.set(isDark);
|
|
222
|
-
this.themeNameSignal.set(isDark ? 'dark' : 'light');
|
|
223
|
-
this.lastChangeSignal.set(new Date());
|
|
224
|
-
this.applyCustomerTheme();
|
|
225
|
+
this.applyTheme(isDark);
|
|
226
|
+
this.saveThemePreference(isDark ? 'dark' : 'light');
|
|
225
227
|
}
|
|
226
228
|
toggleTheme() {
|
|
227
229
|
this.setDarkTheme(!this.isDarkThemeSignal());
|
|
228
230
|
}
|
|
229
231
|
updateTheme(name) {
|
|
230
|
-
this.
|
|
231
|
-
|
|
232
|
+
this.setDarkTheme(name === 'dark');
|
|
233
|
+
}
|
|
234
|
+
/** The visible half: the attribute the stylesheets read, and the derived palette. */
|
|
235
|
+
applyTheme(isDark) {
|
|
236
|
+
if (this.isBrowser) {
|
|
237
|
+
this.document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
|
|
238
|
+
}
|
|
239
|
+
this.isDarkThemeSignal.set(isDark);
|
|
240
|
+
this.themeNameSignal.set(isDark ? 'dark' : 'light');
|
|
232
241
|
this.lastChangeSignal.set(new Date());
|
|
233
|
-
this.saveThemePreference(name);
|
|
234
242
|
this.applyCustomerTheme();
|
|
235
243
|
}
|
|
236
244
|
/**
|
|
@@ -322,7 +330,9 @@ class ThemeService {
|
|
|
322
330
|
const isValid = savedTheme === 'light' || savedTheme === 'dark';
|
|
323
331
|
// No stored preference → honour the OS "prefers-color-scheme" setting.
|
|
324
332
|
const initial = isValid ? savedTheme : this.prefersDarkScheme() ? 'dark' : 'light';
|
|
325
|
-
|
|
333
|
+
// Applied, not saved: with nothing stored the theme follows the OS, and writing the
|
|
334
|
+
// first value read would pin it there forever.
|
|
335
|
+
this.applyTheme(initial === 'dark');
|
|
326
336
|
}
|
|
327
337
|
/** True when the OS/browser requests a dark colour scheme. */
|
|
328
338
|
prefersDarkScheme() {
|
|
@@ -4370,10 +4380,15 @@ class PshInputComponent {
|
|
|
4370
4380
|
}
|
|
4371
4381
|
break;
|
|
4372
4382
|
case 'Escape':
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
this.
|
|
4376
|
-
|
|
4383
|
+
// Only when suggestions are showing. Otherwise the keypress belongs to whatever
|
|
4384
|
+
// encloses the field — a modal, most often — and must reach it.
|
|
4385
|
+
if (this.suggestionsVisible()) {
|
|
4386
|
+
event.preventDefault();
|
|
4387
|
+
event.stopPropagation();
|
|
4388
|
+
this.suggestionsVisible.set(false);
|
|
4389
|
+
this.focusedSuggestionIndex.set(-1);
|
|
4390
|
+
this.syncPanel();
|
|
4391
|
+
}
|
|
4377
4392
|
break;
|
|
4378
4393
|
}
|
|
4379
4394
|
}
|
|
@@ -6859,6 +6874,7 @@ class PshCollapseComponent {
|
|
|
6859
6874
|
case 'Escape':
|
|
6860
6875
|
if (this.expanded()) {
|
|
6861
6876
|
event.preventDefault();
|
|
6877
|
+
event.stopPropagation();
|
|
6862
6878
|
this.close();
|
|
6863
6879
|
}
|
|
6864
6880
|
break;
|
|
@@ -7120,8 +7136,10 @@ class PshDropdownComponent {
|
|
|
7120
7136
|
}
|
|
7121
7137
|
break;
|
|
7122
7138
|
case 'Escape':
|
|
7139
|
+
// Consumed here, so an enclosing modal does not also close on the same keypress.
|
|
7123
7140
|
if (this.isOpen()) {
|
|
7124
7141
|
event.preventDefault();
|
|
7142
|
+
event.stopPropagation();
|
|
7125
7143
|
this.close();
|
|
7126
7144
|
}
|
|
7127
7145
|
break;
|
|
@@ -7152,6 +7170,7 @@ class PshDropdownComponent {
|
|
|
7152
7170
|
break;
|
|
7153
7171
|
case 'Escape':
|
|
7154
7172
|
event.preventDefault();
|
|
7173
|
+
event.stopPropagation();
|
|
7155
7174
|
this.close();
|
|
7156
7175
|
break;
|
|
7157
7176
|
case 'Tab':
|
|
@@ -7682,6 +7701,7 @@ class PshMenuComponent {
|
|
|
7682
7701
|
case 'Escape':
|
|
7683
7702
|
if (this.collapsible() && !this.collapsed()) {
|
|
7684
7703
|
event.preventDefault();
|
|
7704
|
+
event.stopPropagation();
|
|
7685
7705
|
this.toggleCollapse();
|
|
7686
7706
|
}
|
|
7687
7707
|
break;
|
|
@@ -8160,7 +8180,14 @@ class PshSelectComponent {
|
|
|
8160
8180
|
this.focusLast();
|
|
8161
8181
|
break;
|
|
8162
8182
|
case 'Escape':
|
|
8163
|
-
|
|
8183
|
+
// Only when there is a panel to dismiss, and then the event stops here: a modal
|
|
8184
|
+
// listens for Escape on the document, so letting it through would close the whole
|
|
8185
|
+
// dialog — the user's form — for someone who only wanted the list gone.
|
|
8186
|
+
if (this.isOpen()) {
|
|
8187
|
+
event.preventDefault();
|
|
8188
|
+
event.stopPropagation();
|
|
8189
|
+
this.close();
|
|
8190
|
+
}
|
|
8164
8191
|
break;
|
|
8165
8192
|
case 'Tab':
|
|
8166
8193
|
this.close();
|