tosijs-ui 1.0.1 → 1.0.2

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 (93) hide show
  1. package/README.md +4 -2
  2. package/dist/iife.js +70 -60
  3. package/dist/iife.js.map +42 -42
  4. package/dist/index.js +15 -37
  5. package/dist/index.js.map +39 -39
  6. package/dist/version.d.ts +1 -1
  7. package/package.json +2 -2
  8. package/dist/ab-test.js +0 -116
  9. package/dist/babylon-3d.js +0 -292
  10. package/dist/bodymovin-player.js +0 -172
  11. package/dist/bp-loader.js +0 -26
  12. package/dist/carousel.js +0 -308
  13. package/dist/code-editor.js +0 -102
  14. package/dist/color-input.js +0 -112
  15. package/dist/data-table.js +0 -774
  16. package/dist/drag-and-drop.js +0 -386
  17. package/dist/editable-rect.js +0 -450
  18. package/dist/filter-builder.js +0 -468
  19. package/dist/float.js +0 -170
  20. package/dist/form.js +0 -466
  21. package/dist/gamepad.js +0 -115
  22. package/dist/icon-data.js +0 -308
  23. package/dist/icon-types.js +0 -1
  24. package/dist/icons.js +0 -374
  25. package/dist/index-iife.js +0 -4
  26. package/dist/live-example.js +0 -611
  27. package/dist/localize.js +0 -381
  28. package/dist/make-sorter.js +0 -119
  29. package/dist/make-sorter.test.d.ts +0 -1
  30. package/dist/make-sorter.test.js +0 -48
  31. package/dist/mapbox.js +0 -161
  32. package/dist/markdown-viewer.js +0 -173
  33. package/dist/match-shortcut.js +0 -13
  34. package/dist/match-shortcut.test.d.ts +0 -1
  35. package/dist/match-shortcut.test.js +0 -194
  36. package/dist/menu.js +0 -614
  37. package/dist/notifications.js +0 -308
  38. package/dist/password-strength.js +0 -302
  39. package/dist/playwright.config.d.ts +0 -9
  40. package/dist/playwright.config.js +0 -73
  41. package/dist/pop-float.js +0 -231
  42. package/dist/rating.js +0 -192
  43. package/dist/rich-text.js +0 -296
  44. package/dist/segmented.js +0 -298
  45. package/dist/select.js +0 -427
  46. package/dist/side-nav.js +0 -106
  47. package/dist/size-break.js +0 -118
  48. package/dist/sizer.js +0 -92
  49. package/dist/src/ab-test.d.ts +0 -14
  50. package/dist/src/babylon-3d.d.ts +0 -53
  51. package/dist/src/bodymovin-player.d.ts +0 -32
  52. package/dist/src/bp-loader.d.ts +0 -0
  53. package/dist/src/carousel.d.ts +0 -113
  54. package/dist/src/code-editor.d.ts +0 -27
  55. package/dist/src/color-input.d.ts +0 -41
  56. package/dist/src/data-table.d.ts +0 -79
  57. package/dist/src/drag-and-drop.d.ts +0 -2
  58. package/dist/src/editable-rect.d.ts +0 -97
  59. package/dist/src/filter-builder.d.ts +0 -64
  60. package/dist/src/float.d.ts +0 -18
  61. package/dist/src/form.d.ts +0 -68
  62. package/dist/src/gamepad.d.ts +0 -34
  63. package/dist/src/icon-data.d.ts +0 -309
  64. package/dist/src/icon-types.d.ts +0 -7
  65. package/dist/src/icons.d.ts +0 -17
  66. package/dist/src/index.d.ts +0 -37
  67. package/dist/src/live-example.d.ts +0 -51
  68. package/dist/src/localize.d.ts +0 -30
  69. package/dist/src/make-sorter.d.ts +0 -3
  70. package/dist/src/mapbox.d.ts +0 -24
  71. package/dist/src/markdown-viewer.d.ts +0 -15
  72. package/dist/src/match-shortcut.d.ts +0 -9
  73. package/dist/src/menu.d.ts +0 -60
  74. package/dist/src/notifications.d.ts +0 -106
  75. package/dist/src/password-strength.d.ts +0 -35
  76. package/dist/src/pop-float.d.ts +0 -10
  77. package/dist/src/rating.d.ts +0 -62
  78. package/dist/src/rich-text.d.ts +0 -28
  79. package/dist/src/segmented.d.ts +0 -80
  80. package/dist/src/select.d.ts +0 -43
  81. package/dist/src/side-nav.d.ts +0 -36
  82. package/dist/src/size-break.d.ts +0 -18
  83. package/dist/src/sizer.d.ts +0 -34
  84. package/dist/src/tab-selector.d.ts +0 -91
  85. package/dist/src/tag-list.d.ts +0 -37
  86. package/dist/src/track-drag.d.ts +0 -5
  87. package/dist/src/version.d.ts +0 -1
  88. package/dist/src/via-tag.d.ts +0 -2
  89. package/dist/tab-selector.js +0 -326
  90. package/dist/tag-list.js +0 -375
  91. package/dist/track-drag.js +0 -143
  92. package/dist/version.js +0 -1
  93. package/dist/via-tag.js +0 -102
@@ -1,308 +0,0 @@
1
- /*#
2
-
3
- # notifications
4
-
5
- `XinNotification` provides a singleton custom `<xin-notification>` element that manages
6
- a list of notifications.
7
-
8
- The notifications are displayed most-recent first. If the notifications would take more than
9
- half the height of the display, they are scrolled.
10
-
11
- You can post a notification simply with `XinNotification.post()` or `postNotification()`.
12
-
13
- ```
14
- interface NotificationSpec {
15
- message: string
16
- type?: 'success' | 'info' | 'log' | 'warn' | 'error' | 'progress' // default 'info'
17
- icon?: SVGElement | string // defaults to an info icon
18
- duration?: number
19
- progress?: () => number // return percentage completion
20
- close?: () => void
21
- }
22
- ```
23
-
24
- If you provide a `progress` callback (which is assumed to return a number from `0-100`, with
25
- 100+ indicating completion) then `XinNotification` will poll it every second until the
26
- task completes or the notification is closed. Returning 100 or more will automatically close
27
- the notification.
28
-
29
- If you configure a notification's `type = "progress"` but don't provide a `progress` callback
30
- then an indefinite `<progress>` element will be displayed.
31
-
32
- If you provide a `close` callback, it will be fired if the user closes the notification.
33
-
34
- `postNotification` returns a callback function that closes the note programmatically (e.g.
35
- when an operation completes). This will *also* call any `close` callback function you
36
- provided. (The progress demos in the example exercise this functionality.)
37
-
38
- ```js
39
- const { postNotification, icons } = xinjsui
40
-
41
- const form = preview.querySelector('xin-form')
42
- const submit = preview.querySelector('.submit')
43
- const closeButton = preview.querySelector('.close')
44
-
45
- let close
46
-
47
- form.submitCallback = (value, isValid) => {
48
- if (!isValid) return
49
- if (value.type.startsWith('progress')) {
50
- startTime = Date.now()
51
- const { message, duration, icon } = value
52
- close = postNotification({
53
- message,
54
- type: 'progress',
55
- icon,
56
- progress: value.type === 'progress' ? () => (Date.now() - startTime) / (10 * duration) : undefined,
57
- close: () => { postNotification(`${value.message} cancelled`) },
58
- })
59
- } else {
60
- close = postNotification(value)
61
- }
62
- console.log(close)
63
- closeButton.disabled = false
64
- }
65
-
66
- submit.addEventListener('click', form.submit)
67
- closeButton.addEventListener('click', () => {
68
- if (close) {
69
- close()
70
- }
71
- })
72
-
73
- postNotification({
74
- message: 'Welcome to xinjs-ui notifications, this message will disappear in 2s',
75
- duration: 2
76
- })
77
- ```
78
- ```html
79
- <xin-form>
80
- <h3 slot="header">Notification Test</h3>
81
- <xin-field caption="Message" key="message" type="string" value="This is a test…"></xin-field>
82
- <xin-field caption="Type" key="type" value="info">
83
- <xin-select slot="input"
84
- options="error,warn,info,success,log,,progress,progress (indefinite)"
85
- ></xin-select>
86
- </xin-field>
87
- <xin-field caption="Icon" key="icon" value="info">
88
- <xin-select slot="input"
89
- options="info,bug,thumbsUp,thumbsDown,message"
90
- ></xin-select>
91
- </xin-field>
92
- <xin-field caption="Duration" key="duration" type="number" value="2"></xin-field>
93
- <button slot="footer" class="close" disabled>Close Last Notification</button>
94
- <span slot="footer" class="elastic"></span>
95
- <button slot="footer" class="submit">Post Notification</button>
96
- </xin-form>
97
- ```
98
- ```css
99
- xin-form {
100
- height: 100%;
101
- }
102
-
103
- xin-form::part(content) {
104
- display: flex;
105
- flex-direction: column;
106
- padding: 10px;
107
- gap: 10px;
108
- background: var(--background);
109
- }
110
-
111
- xin-form::part(header),
112
- xin-form::part(footer) {
113
- background: #eee;
114
- justify-content: center;
115
- padding: 10px;
116
- }
117
-
118
- xin-form h3 {
119
- margin: 0;
120
- }
121
-
122
- xin-form label {
123
- display: grid;
124
- grid-template-columns: 120px 1fr;
125
- }
126
- ```
127
-
128
- ## `postNotification(spec: NotificationSpec | string)`
129
-
130
- This is simply a wrapper for `XinNotification.post()`.
131
- */
132
- import { Component, elements, vars } from 'xinjs';
133
- import { icons } from './icons';
134
- import { findHighestZ } from './track-drag';
135
- const { div, button } = elements;
136
- const COLOR_MAP = {
137
- error: 'red',
138
- warn: 'orange',
139
- info: 'royalblue',
140
- log: 'gray',
141
- success: 'green',
142
- progress: 'royalblue',
143
- };
144
- export class XinNotification extends Component {
145
- static singleton;
146
- static styleSpec = {
147
- ':host': {
148
- _notificationSpacing: 8,
149
- _notificationWidth: 360,
150
- _notificationPadding: `${vars.notificationSpacing} ${vars.notificationSpacing50} ${vars.notificationSpacing} ${vars.notificationSpacing200}`,
151
- _notificationBg: '#fafafa',
152
- _notificationAccentColor: '#aaa',
153
- _notificationTextColor: '#444',
154
- _notificationIconSize: vars.notificationSpacing300,
155
- _notificationButtonSize: 48,
156
- _notificationBorderWidth: '3px 0 0',
157
- _notificationBorderRadius: vars.notificationSpacing50,
158
- position: 'fixed',
159
- left: 0,
160
- right: 0,
161
- bottom: 0,
162
- paddingBottom: vars.notificationSpacing,
163
- width: vars.notificationWidth,
164
- display: 'flex',
165
- flexDirection: 'column-reverse',
166
- margin: '0 auto',
167
- gap: vars.notificationSpacing,
168
- maxHeight: '50vh',
169
- overflow: 'hidden auto',
170
- boxShadow: 'none !important',
171
- },
172
- ':host *': {
173
- color: vars.notificationTextColor,
174
- },
175
- ':host .note': {
176
- display: 'grid',
177
- background: vars.notificationBg,
178
- padding: vars.notificationPadding,
179
- gridTemplateColumns: `${vars.notificationIconSize} 1fr ${vars.notificationButtonSize}`,
180
- gap: vars.notificationSpacing,
181
- alignItems: 'center',
182
- borderRadius: vars.notificationBorderRadius,
183
- boxShadow: `0 2px 8px #0006, inset 0 0 0 2px ${vars.notificationAccentColor}`,
184
- borderColor: vars.notificationAccentColor,
185
- borderWidth: vars.notificationBorderWidth,
186
- borderStyle: 'solid',
187
- transition: '0.5s ease-in',
188
- transitionProperty: 'margin, opacity',
189
- zIndex: 1,
190
- },
191
- ':host .note .icon': {
192
- stroke: vars.notificationAccentColor,
193
- },
194
- ':host .note button': {
195
- display: 'flex',
196
- lineHeight: vars.notificationButtonSize,
197
- padding: 0,
198
- margin: 0,
199
- height: vars.notificationButtonSize,
200
- width: vars.notificationButtonSize,
201
- background: 'transparent',
202
- alignItems: 'center',
203
- justifyContent: 'center',
204
- boxShadow: 'none',
205
- border: 'none',
206
- position: 'relative',
207
- },
208
- ':host .note button:hover svg': {
209
- stroke: vars.notificationAccentColor,
210
- },
211
- ':host .note button:active svg': {
212
- borderRadius: 99,
213
- stroke: vars.notificationBg,
214
- background: vars.notificationAccentColor,
215
- padding: vars.spacing50,
216
- },
217
- ':host .note svg': {
218
- height: vars.notificationIconSize,
219
- width: vars.notificationIconSize,
220
- pointerEvents: 'none',
221
- },
222
- ':host .message': {
223
- display: 'flex',
224
- flexDirection: 'column',
225
- alignItems: 'center',
226
- gap: vars.notificationSpacing,
227
- },
228
- ':host .note.closing': {
229
- opacity: 0,
230
- zIndex: 0,
231
- },
232
- };
233
- static removeNote(note) {
234
- note.classList.add('closing');
235
- note.style.marginBottom = -note.offsetHeight + 'px';
236
- const remove = () => {
237
- note.remove();
238
- };
239
- note.addEventListener('transitionend', remove);
240
- setTimeout(remove, 1000);
241
- }
242
- static post(spec) {
243
- const { message, duration, type, close, progress, icon } = Object.assign({ type: 'info', duration: -1 }, typeof spec === 'string' ? { message: spec } : spec);
244
- if (!this.singleton) {
245
- this.singleton = xinNotification();
246
- }
247
- const singleton = this.singleton;
248
- document.body.append(singleton);
249
- singleton.style.zIndex = String(findHighestZ() + 1);
250
- const _notificationAccentColor = COLOR_MAP[type];
251
- const progressBar = progress || type === 'progress' ? elements.progress() : {};
252
- const closeCallback = () => {
253
- if (close) {
254
- close();
255
- }
256
- XinNotification.removeNote(note);
257
- };
258
- const iconElement = icon instanceof SVGElement
259
- ? icon
260
- : icon
261
- ? icons[icon]({ class: 'icon' })
262
- : icons.info({ class: 'icon' });
263
- const note = div({
264
- class: `note ${type}`,
265
- style: {
266
- _notificationAccentColor,
267
- },
268
- }, iconElement, div({ class: 'message' }, div(message), progressBar), button({
269
- class: 'close',
270
- title: 'close',
271
- // we can't use onClick because this lives inside a shadowDOM
272
- apply(elt) {
273
- elt.addEventListener('click', closeCallback);
274
- },
275
- }, icons.x()));
276
- singleton.shadowRoot.append(note);
277
- if (progressBar instanceof HTMLProgressElement &&
278
- progress instanceof Function) {
279
- progressBar.setAttribute('max', String(100));
280
- progressBar.value = progress();
281
- const interval = setInterval(() => {
282
- if (!singleton.shadowRoot.contains(note)) {
283
- clearInterval(interval);
284
- return;
285
- }
286
- const percentage = progress();
287
- progressBar.value = percentage;
288
- if (percentage >= 100) {
289
- XinNotification.removeNote(note);
290
- }
291
- }, 1000);
292
- }
293
- if (duration > 0) {
294
- setTimeout(() => {
295
- XinNotification.removeNote(note);
296
- }, duration * 1000);
297
- }
298
- note.scrollIntoView();
299
- return closeCallback;
300
- }
301
- content = null;
302
- }
303
- export const xinNotification = XinNotification.elementCreator({
304
- tag: 'xin-notification',
305
- });
306
- export function postNotification(spec) {
307
- return XinNotification.post(spec);
308
- }
@@ -1,302 +0,0 @@
1
- /*#
2
- # password strength
3
-
4
- Just wrap it a `<xin-password-strength>` element around an `<input>`
5
- and it will gauge its content strength as a password. It will also
6
- let you **securely verify** that the password hasn't been breached.
7
-
8
- ```js
9
- const { xinLocalized, localize } = xinjsui
10
-
11
- const toggle = preview.querySelector('.toggle')
12
- const icon = preview.querySelector('xin-icon')
13
- const input = preview.querySelector('input')
14
- const breach = preview.querySelector('.breach')
15
- const output = preview.querySelector('.output')
16
- const passwordStrength = preview.querySelector('xin-password-strength')
17
-
18
- // Localization Example
19
- passwordStrength.append(xinLocalized({
20
- refString: 'Yes',
21
- localeChanged () {
22
- this.parentElement.strengthDescriptions = [
23
- 'unacceptable',
24
- 'very weak',
25
- 'weak',
26
- 'moderate',
27
- 'strong',
28
- 'very strong',
29
- ].map(localize)
30
- this.parentElement.queueRender()
31
- }
32
- }))
33
-
34
- toggle.addEventListener('click', () => {
35
- if (icon.icon === 'eye') {
36
- input.type = 'text'
37
- icon.icon = 'eyeOff'
38
- } else {
39
- input.type = 'password'
40
- icon.icon = 'eye'
41
- }
42
- })
43
-
44
- breach.addEventListener('click', async () => {
45
- preview.querySelector('xin-password-strength').isBreached().then(isBreached => {
46
- output.textContent =
47
- isBreached
48
- ? 'This password has been breached, look at console for details'
49
- : 'Seems OK'
50
- output.classList.toggle('breached', isBreached)
51
- })
52
- })
53
- ```
54
- ```html
55
- <xin-password-strength>
56
- <input class="password" type="password">
57
- <button class="toggle">
58
- <xin-icon icon="eye"></xin-icon>
59
- </button>
60
- </xin-password-strength>
61
-
62
- <br><br>
63
- <button class="breach">
64
- <xin-localized>Check if breached</xin-localized>
65
- </button>
66
- <div class="output"></div>
67
- ```
68
- ```css
69
- input.password {
70
- box-shadow: inset 0 0 0 2px var(--indicator-color);
71
- }
72
-
73
- .breached {
74
- color: white;
75
- background: red;
76
- }
77
- ```
78
-
79
- ## Algorithm
80
-
81
- The password is assessed to have a strength based on:
82
-
83
- - **length** one point for at least `goodLength` characters long.
84
- - **[a-z]** one point for containing a lowercase letter
85
- - **[A-Z]** one point for containing an uppercase letter
86
- - **[0-9]** one point for containing a numeric character
87
- - **^[a-zA-Z0-9]]** one point for containing some other kind of character
88
-
89
- A password smaller than `minLength` is an automatic `0`.
90
-
91
- ## Attributes
92
-
93
- - `minLength` defaults to `8`
94
- - `goodLength` defaults to `12`
95
- - `indicatorColors` six HTML colors, separated by commas, defaults to `'#f00,#f40,#f80,#ef0,#8f0,#0d4'`
96
- - `descriptionColors` six HTML colors, sepeated by commans, defaults to `'#000,#000,#000,#000,#000,#fff'`
97
-
98
- ## Properties
99
-
100
- - `value`, `strength` is a number from 0 to 5
101
- - `issues` is a structure which you can use to generate feedback
102
-
103
- ```
104
- <xin-password-strength>.issues = {
105
- tooShort: boolean,
106
- short: boolean,
107
- noUpper: boolean,
108
- noLower: boolean,
109
- noNumber: boolean,
110
- noSpecial: boolean,
111
- }
112
- ```
113
-
114
- ## Customizing / Localizing Strings
115
-
116
- The following properties control the feedback generated.
117
-
118
- ```
119
- issueDescriptions = {
120
- tooShort: 'too short',
121
- short: 'short',
122
- noUpper: 'no upper case',
123
- noLower: 'no lower case',
124
- noNumber: 'no digits',
125
- noSpecial: 'no unusual characters',
126
- }
127
- ```
128
-
129
- ```
130
- strengthDescriptions = [
131
- 'unacceptable',
132
- 'very weak',
133
- 'weak',
134
- 'moderate',
135
- 'strong',
136
- 'very strong',
137
- ]
138
- ```
139
-
140
- ## `isBreached()`
141
-
142
- `<xin-password-meter>` also provides an `isBreached(): Promise<boolean>` method
143
- which uses [weakpass.com's API](https://weakpass.com/) to tell you if the password has been
144
- breached.
145
-
146
- > Note that `isBreached` does not send the plain-text password anywhere. It uses **SHA-1**
147
- to hash the password and then sends that for lookup.
148
-
149
- ## Utility Functions
150
-
151
- Two functions used internally for querying [Weakpass,com](https://weakpass.com/) are
152
- provided in case they're useful on their own.
153
-
154
- `isBreached(password: striing): Promise<boolean>` will return `true` if the password is
155
- found in Weakpass's database (and spit out extra info to the console).
156
-
157
- `digest(s: string, method="sha-1"): Promise<string>` is just a nice wrapper for `crypto.digest`.
158
- */
159
- import { Component, elements, vars, varDefault } from 'xinjs';
160
- export const digest = async (s, method = 'SHA-1') => {
161
- // Convert password to an ArrayBuffer
162
- const encoder = new TextEncoder();
163
- const data = encoder.encode(s);
164
- // Hash the password using SHA-1
165
- const hashBuffer = await crypto.subtle.digest(method, data);
166
- // Convert the hash to a hexadecimal string
167
- const hashArray = Array.from(new Uint8Array(hashBuffer));
168
- const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
169
- return hashHex;
170
- };
171
- export const isBreached = async (password) => {
172
- const hashHex = await digest(password);
173
- const response = await fetch(`https://weakpass.com/api/v1/search/${hashHex}`);
174
- if (response.ok) {
175
- const result = await response.json();
176
- console.log('password found in weakpass database', result);
177
- }
178
- return response.status !== 404;
179
- };
180
- const { span, xinSlot } = elements;
181
- export class XinPasswordStrength extends Component {
182
- minLength = 8;
183
- goodLength = 12;
184
- indicatorColors = '#f00,#f40,#f80,#ef0,#8f0,#0a2';
185
- descriptionColors = '#000,#000,#000,#000,#000,#fff';
186
- issues = {
187
- tooShort: true,
188
- short: true,
189
- noUpper: true,
190
- noLower: true,
191
- noNumber: true,
192
- noSpecial: true,
193
- };
194
- issueDescriptions = {
195
- tooShort: 'too short',
196
- short: 'short',
197
- noUpper: 'no upper case',
198
- noLower: 'no lower case',
199
- noNumber: 'no digits',
200
- noSpecial: 'no unusual characters',
201
- };
202
- value = 0;
203
- strengthDescriptions = [
204
- 'unacceptable',
205
- 'very weak',
206
- 'weak',
207
- 'moderate',
208
- 'strong',
209
- 'very strong',
210
- ];
211
- constructor() {
212
- super();
213
- this.initAttributes('minLength', 'goodLength', 'indicatorColors');
214
- }
215
- strength(password) {
216
- this.issues = {
217
- tooShort: password.length < this.minLength,
218
- short: password.length < this.goodLength,
219
- noUpper: !password.match(/[A-Z]/),
220
- noLower: !password.match(/[a-z]/),
221
- noNumber: !password.match(/[0-9]/),
222
- noSpecial: !password.match(/[^a-zA-Z0-9]/),
223
- };
224
- return this.issues.tooShort
225
- ? 0
226
- : Object.values(this.issues).filter((v) => !v).length - 1;
227
- }
228
- async isBreached() {
229
- const password = this.querySelector('input')?.value;
230
- if (!password || typeof password !== 'string') {
231
- return true;
232
- }
233
- return await isBreached(password);
234
- }
235
- updateIndicator = (password) => {
236
- const { level, description } = this.parts;
237
- const colors = this.indicatorColors.split(',');
238
- const descriptionColors = this.descriptionColors.split(',');
239
- const strength = this.strength(password);
240
- if (this.value !== strength) {
241
- this.value = strength;
242
- this.dispatchEvent(new Event('change'));
243
- }
244
- level.style.width = `${(strength + 1) * 16.67}%`;
245
- this.style.setProperty('--indicator-color', colors[strength]);
246
- this.style.setProperty('--description-color', descriptionColors[strength]);
247
- description.textContent = this.strengthDescriptions[strength];
248
- };
249
- update = (event) => {
250
- const input = event.target.closest('input');
251
- this.updateIndicator(input?.value || '');
252
- };
253
- content = () => [
254
- xinSlot({ onInput: this.update }),
255
- span({ part: 'meter' }, span({ part: 'level' }), span({ part: 'description' })),
256
- ];
257
- render() {
258
- super.render();
259
- const input = this.querySelector('input');
260
- this.updateIndicator(input?.value);
261
- }
262
- }
263
- export const xinPasswordStrength = XinPasswordStrength.elementCreator({
264
- tag: 'xin-password-strength',
265
- styleSpec: {
266
- ':host': {
267
- display: 'inline-flex',
268
- flexDirection: 'column',
269
- gap: vars.spacing50,
270
- position: 'relative',
271
- },
272
- ':host xin-slot': {
273
- display: 'flex',
274
- },
275
- ':host [part="meter"]': {
276
- display: 'block',
277
- position: 'relative',
278
- height: varDefault.meterHeight('24px'),
279
- background: varDefault.indicatorBg('white'),
280
- borderRadius: varDefault.meterRadius('4px'),
281
- boxShadow: varDefault.meterShadow(`inset 0 0 0 2px ${vars.indicatorColor}`),
282
- },
283
- ':host [part="level"]': {
284
- height: varDefault.levelHeight('20px'),
285
- content: '" "',
286
- display: 'inline-block',
287
- width: 0,
288
- transition: '0.15s ease-out',
289
- background: vars.indicatorColor,
290
- margin: varDefault.levelMargin('2px'),
291
- borderRadius: varDefault.levelRadius('2px'),
292
- },
293
- ':host [part="description"]': {
294
- position: 'absolute',
295
- inset: '0',
296
- color: vars.descriptionColor,
297
- height: varDefault.meterHeight('24px'),
298
- lineHeight: varDefault.meterHeight('24px'),
299
- textAlign: 'center',
300
- },
301
- },
302
- });
@@ -1,9 +0,0 @@
1
- /**
2
- * Read environment variables from file.
3
- * https://github.com/motdotla/dotenv
4
- */
5
- /**
6
- * See https://playwright.dev/docs/test-configuration.
7
- */
8
- declare const _default: import("@playwright/test").PlaywrightTestConfig<{}, {}>;
9
- export default _default;
@@ -1,73 +0,0 @@
1
- import { defineConfig, devices } from '@playwright/test';
2
- /**
3
- * Read environment variables from file.
4
- * https://github.com/motdotla/dotenv
5
- */
6
- // import dotenv from 'dotenv';
7
- // dotenv.config({ path: path.resolve(__dirname, '.env') });
8
- /**
9
- * See https://playwright.dev/docs/test-configuration.
10
- */
11
- export default defineConfig({
12
- testDir: './tests',
13
- /* Run tests in files in parallel */
14
- fullyParallel: true,
15
- /* Fail the build on CI if you accidentally left test.only in the source code. */
16
- forbidOnly: !!process.env.CI,
17
- /* Retry on CI only */
18
- retries: process.env.CI ? 2 : 0,
19
- /* Opt out of parallel tests on CI. */
20
- workers: process.env.CI ? 1 : undefined,
21
- /* Reporter to use. See https://playwright.dev/docs/test-reporters */
22
- reporter: 'html',
23
- /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
24
- /* use .pw.ts for playwright (vs. bun) tests */
25
- testMatch: /.*\.pw\.ts/,
26
- use: {
27
- /* Base URL to use in actions like `await page.goto('/')`. */
28
- // baseURL: 'http://127.0.0.1:3000',
29
- /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
30
- trace: 'on-first-retry',
31
- /* allow https on localhost with self-signed certificate */
32
- ignoreHTTPSErrors: true,
33
- },
34
- /* Configure projects for major browsers */
35
- projects: [
36
- {
37
- name: 'chromium',
38
- use: { ...devices['Desktop Chrome'] },
39
- },
40
- {
41
- name: 'firefox',
42
- use: { ...devices['Desktop Firefox'] },
43
- },
44
- {
45
- name: 'webkit',
46
- use: { ...devices['Desktop Safari'] },
47
- },
48
- /* Test against mobile viewports. */
49
- // {
50
- // name: 'Mobile Chrome',
51
- // use: { ...devices['Pixel 5'] },
52
- // },
53
- // {
54
- // name: 'Mobile Safari',
55
- // use: { ...devices['iPhone 12'] },
56
- // },
57
- /* Test against branded browsers. */
58
- // {
59
- // name: 'Microsoft Edge',
60
- // use: { ...devices['Desktop Edge'], channel: 'msedge' },
61
- // },
62
- // {
63
- // name: 'Google Chrome',
64
- // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
65
- // },
66
- ],
67
- /* Run your local dev server before starting the tests */
68
- // webServer: {
69
- // command: 'npm run start',
70
- // url: 'http://127.0.0.1:3000',
71
- // reuseExistingServer: !process.env.CI,
72
- // },
73
- });