@furystack/shades-common-components 10.0.35 → 11.0.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/CHANGELOG.md +66 -0
- package/esm/components/animations.spec.d.ts +2 -0
- package/esm/components/animations.spec.d.ts.map +1 -0
- package/esm/components/animations.spec.js +201 -0
- package/esm/components/animations.spec.js.map +1 -0
- package/esm/components/app-bar-link.js +21 -20
- package/esm/components/app-bar-link.js.map +1 -1
- package/esm/components/app-bar-link.spec.d.ts +2 -0
- package/esm/components/app-bar-link.spec.d.ts.map +1 -0
- package/esm/components/app-bar-link.spec.js +252 -0
- package/esm/components/app-bar-link.spec.js.map +1 -0
- package/esm/components/app-bar.js +21 -21
- package/esm/components/app-bar.js.map +1 -1
- package/esm/components/app-bar.spec.d.ts +2 -0
- package/esm/components/app-bar.spec.d.ts.map +1 -0
- package/esm/components/app-bar.spec.js +117 -0
- package/esm/components/app-bar.spec.js.map +1 -0
- package/esm/components/avatar.d.ts.map +1 -1
- package/esm/components/avatar.js +15 -19
- package/esm/components/avatar.js.map +1 -1
- package/esm/components/avatar.spec.d.ts +2 -0
- package/esm/components/avatar.spec.d.ts.map +1 -0
- package/esm/components/avatar.spec.js +114 -0
- package/esm/components/avatar.spec.js.map +1 -0
- package/esm/components/button.d.ts.map +1 -1
- package/esm/components/button.js +145 -156
- package/esm/components/button.js.map +1 -1
- package/esm/components/button.spec.d.ts +2 -0
- package/esm/components/button.spec.d.ts.map +1 -0
- package/esm/components/button.spec.js +155 -0
- package/esm/components/button.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-input.d.ts.map +1 -1
- package/esm/components/command-palette/command-palette-input.js +18 -16
- package/esm/components/command-palette/command-palette-input.js.map +1 -1
- package/esm/components/command-palette/command-palette-input.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-input.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-input.spec.js +233 -0
- package/esm/components/command-palette/command-palette-input.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-manager.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-manager.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-manager.spec.js +362 -0
- package/esm/components/command-palette/command-palette-manager.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-suggestion-list.d.ts.map +1 -1
- package/esm/components/command-palette/command-palette-suggestion-list.js +42 -46
- package/esm/components/command-palette/command-palette-suggestion-list.js.map +1 -1
- package/esm/components/command-palette/command-palette-suggestion-list.spec.d.ts +2 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.d.ts.map +1 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js +376 -0
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -0
- package/esm/components/command-palette/index.d.ts.map +1 -1
- package/esm/components/command-palette/index.js +100 -110
- package/esm/components/command-palette/index.js.map +1 -1
- package/esm/components/command-palette/index.spec.d.ts +2 -0
- package/esm/components/command-palette/index.spec.d.ts.map +1 -0
- package/esm/components/command-palette/index.spec.js +509 -0
- package/esm/components/command-palette/index.spec.js.map +1 -0
- package/esm/components/data-grid/body.js +1 -1
- package/esm/components/data-grid/body.js.map +1 -1
- package/esm/components/data-grid/body.spec.d.ts +2 -0
- package/esm/components/data-grid/body.spec.d.ts.map +1 -0
- package/esm/components/data-grid/body.spec.js +228 -0
- package/esm/components/data-grid/body.spec.js.map +1 -0
- package/esm/components/data-grid/data-grid-row.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid-row.js +49 -73
- package/esm/components/data-grid/data-grid-row.js.map +1 -1
- package/esm/components/data-grid/data-grid-row.spec.d.ts +2 -0
- package/esm/components/data-grid/data-grid-row.spec.d.ts.map +1 -0
- package/esm/components/data-grid/data-grid-row.spec.js +296 -0
- package/esm/components/data-grid/data-grid-row.spec.js.map +1 -0
- package/esm/components/data-grid/data-grid.d.ts.map +1 -1
- package/esm/components/data-grid/data-grid.js +35 -28
- package/esm/components/data-grid/data-grid.js.map +1 -1
- package/esm/components/data-grid/data-grid.spec.d.ts +2 -0
- package/esm/components/data-grid/data-grid.spec.d.ts.map +1 -0
- package/esm/components/data-grid/data-grid.spec.js +544 -0
- package/esm/components/data-grid/data-grid.spec.js.map +1 -0
- package/esm/components/data-grid/footer.js +21 -15
- package/esm/components/data-grid/footer.js.map +1 -1
- package/esm/components/data-grid/footer.spec.d.ts +2 -0
- package/esm/components/data-grid/footer.spec.d.ts.map +1 -0
- package/esm/components/data-grid/footer.spec.js +264 -0
- package/esm/components/data-grid/footer.spec.js.map +1 -0
- package/esm/components/data-grid/header.d.ts.map +1 -1
- package/esm/components/data-grid/header.js +55 -33
- package/esm/components/data-grid/header.js.map +1 -1
- package/esm/components/data-grid/header.spec.d.ts +2 -0
- package/esm/components/data-grid/header.spec.d.ts.map +1 -0
- package/esm/components/data-grid/header.spec.js +421 -0
- package/esm/components/data-grid/header.spec.js.map +1 -0
- package/esm/components/data-grid/selection-cell.d.ts.map +1 -1
- package/esm/components/data-grid/selection-cell.js +13 -6
- package/esm/components/data-grid/selection-cell.js.map +1 -1
- package/esm/components/data-grid/selection-cell.spec.d.ts +2 -0
- package/esm/components/data-grid/selection-cell.spec.d.ts.map +1 -0
- package/esm/components/data-grid/selection-cell.spec.js +118 -0
- package/esm/components/data-grid/selection-cell.spec.js.map +1 -0
- package/esm/components/fab.d.ts.map +1 -1
- package/esm/components/fab.js +10 -1
- package/esm/components/fab.js.map +1 -1
- package/esm/components/fab.spec.d.ts +2 -0
- package/esm/components/fab.spec.d.ts.map +1 -0
- package/esm/components/fab.spec.js +95 -0
- package/esm/components/fab.spec.js.map +1 -0
- package/esm/components/form.spec.d.ts +2 -0
- package/esm/components/form.spec.d.ts.map +1 -0
- package/esm/components/form.spec.js +314 -0
- package/esm/components/form.spec.js.map +1 -0
- package/esm/components/grid.d.ts.map +1 -1
- package/esm/components/grid.js +40 -37
- package/esm/components/grid.js.map +1 -1
- package/esm/components/grid.spec.d.ts +2 -0
- package/esm/components/grid.spec.d.ts.map +1 -0
- package/esm/components/grid.spec.js +316 -0
- package/esm/components/grid.spec.js.map +1 -0
- package/esm/components/inputs/autocomplete.spec.d.ts +2 -0
- package/esm/components/inputs/autocomplete.spec.d.ts.map +1 -0
- package/esm/components/inputs/autocomplete.spec.js +194 -0
- package/esm/components/inputs/autocomplete.spec.js.map +1 -0
- package/esm/components/inputs/input.d.ts.map +1 -1
- package/esm/components/inputs/input.js +141 -109
- package/esm/components/inputs/input.js.map +1 -1
- package/esm/components/inputs/input.spec.d.ts +2 -0
- package/esm/components/inputs/input.spec.d.ts.map +1 -0
- package/esm/components/inputs/input.spec.js +577 -0
- package/esm/components/inputs/input.spec.js.map +1 -0
- package/esm/components/inputs/text-area.d.ts.map +1 -1
- package/esm/components/inputs/text-area.js +54 -58
- package/esm/components/inputs/text-area.js.map +1 -1
- package/esm/components/inputs/text-area.spec.d.ts +2 -0
- package/esm/components/inputs/text-area.spec.d.ts.map +1 -0
- package/esm/components/inputs/text-area.spec.js +214 -0
- package/esm/components/inputs/text-area.spec.js.map +1 -0
- package/esm/components/loader.js +1 -1
- package/esm/components/loader.js.map +1 -1
- package/esm/components/loader.spec.d.ts +2 -0
- package/esm/components/loader.spec.d.ts.map +1 -0
- package/esm/components/loader.spec.js +251 -0
- package/esm/components/loader.spec.js.map +1 -0
- package/esm/components/modal.d.ts.map +1 -1
- package/esm/components/modal.js +11 -9
- package/esm/components/modal.js.map +1 -1
- package/esm/components/modal.spec.d.ts +2 -0
- package/esm/components/modal.spec.d.ts.map +1 -0
- package/esm/components/modal.spec.js +227 -0
- package/esm/components/modal.spec.js.map +1 -0
- package/esm/components/noty-list.d.ts.map +1 -1
- package/esm/components/noty-list.js +39 -40
- package/esm/components/noty-list.js.map +1 -1
- package/esm/components/noty-list.spec.d.ts +2 -0
- package/esm/components/noty-list.spec.d.ts.map +1 -0
- package/esm/components/noty-list.spec.js +486 -0
- package/esm/components/noty-list.spec.js.map +1 -0
- package/esm/components/paper.d.ts.map +1 -1
- package/esm/components/paper.js +15 -12
- package/esm/components/paper.js.map +1 -1
- package/esm/components/paper.spec.d.ts +2 -0
- package/esm/components/paper.spec.d.ts.map +1 -0
- package/esm/components/paper.spec.js +63 -0
- package/esm/components/paper.spec.js.map +1 -0
- package/esm/components/skeleton.js +1 -1
- package/esm/components/skeleton.js.map +1 -1
- package/esm/components/skeleton.spec.d.ts +2 -0
- package/esm/components/skeleton.spec.d.ts.map +1 -0
- package/esm/components/skeleton.spec.js +159 -0
- package/esm/components/skeleton.spec.js.map +1 -0
- package/esm/components/styles.spec.d.ts +2 -0
- package/esm/components/styles.spec.d.ts.map +1 -0
- package/esm/components/styles.spec.js +56 -0
- package/esm/components/styles.spec.js.map +1 -0
- package/esm/components/suggest/index.d.ts.map +1 -1
- package/esm/components/suggest/index.js +74 -83
- package/esm/components/suggest/index.js.map +1 -1
- package/esm/components/suggest/index.spec.d.ts +2 -0
- package/esm/components/suggest/index.spec.d.ts.map +1 -0
- package/esm/components/suggest/index.spec.js +515 -0
- package/esm/components/suggest/index.spec.js.map +1 -0
- package/esm/components/suggest/suggest-input.d.ts.map +1 -1
- package/esm/components/suggest/suggest-input.js +16 -17
- package/esm/components/suggest/suggest-input.js.map +1 -1
- package/esm/components/suggest/suggest-input.spec.d.ts +2 -0
- package/esm/components/suggest/suggest-input.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggest-input.spec.js +138 -0
- package/esm/components/suggest/suggest-input.spec.js.map +1 -0
- package/esm/components/suggest/suggest-manager.spec.d.ts +2 -0
- package/esm/components/suggest/suggest-manager.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggest-manager.spec.js +308 -0
- package/esm/components/suggest/suggest-manager.spec.js.map +1 -0
- package/esm/components/suggest/suggestion-list.d.ts.map +1 -1
- package/esm/components/suggest/suggestion-list.js +43 -48
- package/esm/components/suggest/suggestion-list.js.map +1 -1
- package/esm/components/suggest/suggestion-list.spec.d.ts +2 -0
- package/esm/components/suggest/suggestion-list.spec.d.ts.map +1 -0
- package/esm/components/suggest/suggestion-list.spec.js +252 -0
- package/esm/components/suggest/suggestion-list.spec.js.map +1 -0
- package/esm/components/tabs.d.ts.map +1 -1
- package/esm/components/tabs.js +32 -18
- package/esm/components/tabs.js.map +1 -1
- package/esm/components/tabs.spec.d.ts +2 -0
- package/esm/components/tabs.spec.d.ts.map +1 -0
- package/esm/components/tabs.spec.js +187 -0
- package/esm/components/tabs.spec.js.map +1 -0
- package/esm/components/wizard/index.d.ts.map +1 -1
- package/esm/components/wizard/index.js +10 -7
- package/esm/components/wizard/index.js.map +1 -1
- package/esm/components/wizard/index.spec.d.ts +2 -0
- package/esm/components/wizard/index.spec.d.ts.map +1 -0
- package/esm/components/wizard/index.spec.js +171 -0
- package/esm/components/wizard/index.spec.js.map +1 -0
- package/esm/services/collection-service.spec.js +391 -2
- package/esm/services/collection-service.spec.js.map +1 -1
- package/esm/services/css-variable-theme.d.ts.map +1 -1
- package/esm/services/css-variable-theme.js +21 -1
- package/esm/services/css-variable-theme.js.map +1 -1
- package/esm/services/css-variable-theme.spec.d.ts +2 -0
- package/esm/services/css-variable-theme.spec.d.ts.map +1 -0
- package/esm/services/css-variable-theme.spec.js +169 -0
- package/esm/services/css-variable-theme.spec.js.map +1 -0
- package/esm/services/default-palette.d.ts +4 -0
- package/esm/services/default-palette.d.ts.map +1 -1
- package/esm/services/default-palette.js +22 -0
- package/esm/services/default-palette.js.map +1 -1
- package/esm/services/theme-provider-service.d.ts +59 -1
- package/esm/services/theme-provider-service.d.ts.map +1 -1
- package/esm/services/theme-provider-service.js.map +1 -1
- package/esm/services/theme-provider-service.spec.d.ts +2 -0
- package/esm/services/theme-provider-service.spec.d.ts.map +1 -0
- package/esm/services/theme-provider-service.spec.js +166 -0
- package/esm/services/theme-provider-service.spec.js.map +1 -0
- package/package.json +2 -2
- package/src/components/animations.spec.ts +299 -0
- package/src/components/app-bar-link.spec.tsx +341 -0
- package/src/components/app-bar-link.tsx +21 -21
- package/src/components/app-bar.spec.tsx +142 -0
- package/src/components/app-bar.tsx +22 -22
- package/src/components/avatar.spec.tsx +146 -0
- package/src/components/avatar.tsx +17 -20
- package/src/components/button.spec.tsx +193 -0
- package/src/components/button.tsx +162 -197
- package/src/components/command-palette/command-palette-input.spec.tsx +320 -0
- package/src/components/command-palette/command-palette-input.tsx +19 -22
- package/src/components/command-palette/command-palette-manager.spec.ts +470 -0
- package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +499 -0
- package/src/components/command-palette/command-palette-suggestion-list.tsx +42 -46
- package/src/components/command-palette/index.spec.tsx +684 -0
- package/src/components/command-palette/index.tsx +107 -136
- package/src/components/data-grid/body.spec.tsx +340 -0
- package/src/components/data-grid/body.tsx +1 -1
- package/src/components/data-grid/data-grid-row.spec.tsx +382 -0
- package/src/components/data-grid/data-grid-row.tsx +50 -82
- package/src/components/data-grid/data-grid.spec.tsx +939 -0
- package/src/components/data-grid/data-grid.tsx +38 -35
- package/src/components/data-grid/footer.spec.tsx +344 -0
- package/src/components/data-grid/footer.tsx +19 -19
- package/src/components/data-grid/header.spec.tsx +563 -0
- package/src/components/data-grid/header.tsx +53 -44
- package/src/components/data-grid/selection-cell.spec.tsx +150 -0
- package/src/components/data-grid/selection-cell.tsx +12 -6
- package/src/components/fab.spec.tsx +108 -0
- package/src/components/fab.tsx +10 -1
- package/src/components/form.spec.tsx +481 -0
- package/src/components/grid.spec.tsx +334 -0
- package/src/components/grid.tsx +57 -63
- package/src/components/inputs/autocomplete.spec.tsx +258 -0
- package/src/components/inputs/input.spec.tsx +808 -0
- package/src/components/inputs/input.tsx +153 -139
- package/src/components/inputs/text-area.spec.tsx +285 -0
- package/src/components/inputs/text-area.tsx +53 -79
- package/src/components/loader.spec.tsx +346 -0
- package/src/components/loader.tsx +1 -1
- package/src/components/modal.spec.tsx +304 -0
- package/src/components/modal.tsx +11 -9
- package/src/components/noty-list.spec.tsx +631 -0
- package/src/components/noty-list.tsx +39 -50
- package/src/components/paper.spec.tsx +72 -0
- package/src/components/paper.tsx +15 -13
- package/src/components/skeleton.spec.tsx +219 -0
- package/src/components/skeleton.tsx +1 -1
- package/src/components/styles.spec.ts +70 -0
- package/src/components/suggest/index.spec.tsx +861 -0
- package/src/components/suggest/index.tsx +74 -101
- package/src/components/suggest/suggest-input.spec.tsx +181 -0
- package/src/components/suggest/suggest-input.tsx +16 -24
- package/src/components/suggest/suggest-manager.spec.ts +409 -0
- package/src/components/suggest/suggestion-list.spec.tsx +334 -0
- package/src/components/suggest/suggestion-list.tsx +43 -48
- package/src/components/tabs.spec.tsx +236 -0
- package/src/components/tabs.tsx +33 -21
- package/src/components/wizard/index.spec.tsx +224 -0
- package/src/components/wizard/index.tsx +10 -9
- package/src/services/collection-service.spec.ts +492 -3
- package/src/services/css-variable-theme.spec.ts +204 -0
- package/src/services/css-variable-theme.ts +21 -1
- package/src/services/default-palette.ts +22 -0
- package/src/services/theme-provider-service.spec.ts +195 -0
- package/src/services/theme-provider-service.ts +60 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PartialElement } from '@furystack/shades'
|
|
2
|
-
import { Shade,
|
|
2
|
+
import { Shade, createComponent } from '@furystack/shades'
|
|
3
3
|
import { ObservableValue } from '@furystack/utils'
|
|
4
|
+
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
4
5
|
import type { Palette } from '../../services/theme-provider-service.js'
|
|
5
6
|
import { ThemeProviderService } from '../../services/theme-provider-service.js'
|
|
6
7
|
import { FormService } from '../form.js'
|
|
@@ -74,76 +75,24 @@ export type TextInputState = {
|
|
|
74
75
|
element: JSX.Element<TextInputProps>
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Sets CSS custom properties for dynamic color values.
|
|
80
|
+
* State-based styling (focus, error, disabled) is handled by CSS selectors.
|
|
81
|
+
* Background colors use CSS color-mix() for automatic theme adaptation.
|
|
82
|
+
*/
|
|
83
|
+
const setInputColors = ({
|
|
84
|
+
element,
|
|
78
85
|
themeProvider,
|
|
79
86
|
props,
|
|
80
|
-
state,
|
|
81
|
-
validationResult,
|
|
82
87
|
}: {
|
|
88
|
+
element: HTMLElement
|
|
83
89
|
themeProvider: ThemeProviderService
|
|
84
90
|
props: TextInputProps
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const isContained = props.variant === 'contained'
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
display: 'flex',
|
|
94
|
-
flexDirection: 'column',
|
|
95
|
-
alignItems: 'flex-start',
|
|
96
|
-
justifyContent: 'space-between',
|
|
97
|
-
fontSize: '11px',
|
|
98
|
-
fontWeight: '500',
|
|
99
|
-
letterSpacing: '0.01em',
|
|
100
|
-
color: props.disabled
|
|
101
|
-
? themeProvider.theme.text.disabled
|
|
102
|
-
: isError
|
|
103
|
-
? themeProvider.theme.palette.error.main
|
|
104
|
-
: state.focused
|
|
105
|
-
? themeProvider.theme.palette[props.defaultColor || 'primary'].main
|
|
106
|
-
: themeProvider.theme.text.secondary,
|
|
107
|
-
marginBottom: '1.25em',
|
|
108
|
-
padding: '12px 14px',
|
|
109
|
-
borderRadius: '8px',
|
|
110
|
-
background: isContained
|
|
111
|
-
? themeProvider
|
|
112
|
-
.getRgbFromColorString(
|
|
113
|
-
isError
|
|
114
|
-
? themeProvider.theme.palette.error.main
|
|
115
|
-
: themeProvider.theme.palette[props.defaultColor || 'primary'].main,
|
|
116
|
-
)
|
|
117
|
-
.update('a', state.focused ? 0.12 : 0.08)
|
|
118
|
-
.toString()
|
|
119
|
-
: 'transparent',
|
|
120
|
-
border:
|
|
121
|
-
isOutlined || isContained
|
|
122
|
-
? `2px solid ${
|
|
123
|
-
isError
|
|
124
|
-
? themeProvider.theme.palette.error.main
|
|
125
|
-
: state.focused
|
|
126
|
-
? themeProvider.theme.palette[props.defaultColor || 'primary'].main
|
|
127
|
-
: themeProvider.getRgbFromColorString(themeProvider.theme.text.secondary).update('a', 0.3).toString()
|
|
128
|
-
}`
|
|
129
|
-
: `2px solid transparent`,
|
|
130
|
-
boxShadow:
|
|
131
|
-
state.focused && !props.disabled
|
|
132
|
-
? `0 0 0 3px ${themeProvider
|
|
133
|
-
.getRgbFromColorString(
|
|
134
|
-
isError
|
|
135
|
-
? themeProvider.theme.palette.error.main
|
|
136
|
-
: themeProvider.theme.palette[props.defaultColor || 'primary'].main,
|
|
137
|
-
)
|
|
138
|
-
.update('a', 0.15)
|
|
139
|
-
.toString()}`
|
|
140
|
-
: 'none',
|
|
141
|
-
filter: props.disabled ? 'grayscale(100%)' : 'none',
|
|
142
|
-
opacity: props.disabled ? '0.5' : '1',
|
|
143
|
-
transition: 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
|
|
144
|
-
cursor: props.disabled ? 'not-allowed' : 'text',
|
|
145
|
-
...props.labelProps?.style,
|
|
146
|
-
}
|
|
91
|
+
}): void => {
|
|
92
|
+
// Only set the color variables - backgrounds use CSS color-mix()
|
|
93
|
+
const primaryColor = themeProvider.theme.palette[props.defaultColor || 'primary'].main
|
|
94
|
+
element.style.setProperty('--input-primary-color', primaryColor)
|
|
95
|
+
element.style.setProperty('--input-error-color', themeProvider.theme.palette.error.main)
|
|
147
96
|
}
|
|
148
97
|
|
|
149
98
|
const getDefaultMessagesForValidityState = (state: ValidityState) => {
|
|
@@ -180,6 +129,120 @@ const getDefaultMessagesForValidityState = (state: ValidityState) => {
|
|
|
180
129
|
|
|
181
130
|
export const Input = Shade<TextInputProps>({
|
|
182
131
|
shadowDomName: 'shade-input',
|
|
132
|
+
css: {
|
|
133
|
+
display: 'block',
|
|
134
|
+
marginBottom: '1.25em',
|
|
135
|
+
|
|
136
|
+
// Base label styles
|
|
137
|
+
'& label': {
|
|
138
|
+
display: 'flex',
|
|
139
|
+
flexDirection: 'column',
|
|
140
|
+
alignItems: 'flex-start',
|
|
141
|
+
justifyContent: 'space-between',
|
|
142
|
+
fontSize: '11px',
|
|
143
|
+
fontWeight: '500',
|
|
144
|
+
letterSpacing: '0.01em',
|
|
145
|
+
padding: '12px 14px',
|
|
146
|
+
borderRadius: '8px',
|
|
147
|
+
transition: 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
|
|
148
|
+
cursor: 'text',
|
|
149
|
+
color: cssVariableTheme.text.secondary,
|
|
150
|
+
background: 'transparent',
|
|
151
|
+
border: '2px solid transparent',
|
|
152
|
+
boxShadow: 'none',
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
// Outlined variant - default border
|
|
156
|
+
'&[data-variant="outlined"] label': {
|
|
157
|
+
borderColor: 'rgba(128, 128, 128, 0.3)',
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
// Contained variant - background using color-mix for theme-aware alpha
|
|
161
|
+
'&[data-variant="contained"] label': {
|
|
162
|
+
borderColor: 'rgba(128, 128, 128, 0.3)',
|
|
163
|
+
background: 'color-mix(in srgb, var(--input-primary-color) 8%, transparent)',
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
// Focus state using :focus-within (color change for all variants)
|
|
167
|
+
'&:focus-within label': {
|
|
168
|
+
color: 'var(--input-primary-color)',
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
// Focus state for outlined/contained variants - add border and shadow
|
|
172
|
+
'&[data-variant="outlined"]:focus-within label, &[data-variant="contained"]:focus-within label': {
|
|
173
|
+
borderColor: 'var(--input-primary-color)',
|
|
174
|
+
boxShadow: '0 0 0 3px rgba(128, 128, 128, 0.15)',
|
|
175
|
+
},
|
|
176
|
+
'&[data-variant="contained"]:focus-within label': {
|
|
177
|
+
background: 'color-mix(in srgb, var(--input-primary-color) 12%, transparent)',
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
// Invalid/error state
|
|
181
|
+
'&[data-invalid] label': {
|
|
182
|
+
color: 'var(--input-error-color)',
|
|
183
|
+
},
|
|
184
|
+
'&[data-invalid][data-variant="outlined"] label, &[data-invalid][data-variant="contained"] label': {
|
|
185
|
+
borderColor: 'var(--input-error-color)',
|
|
186
|
+
},
|
|
187
|
+
'&[data-invalid][data-variant="contained"] label': {
|
|
188
|
+
background: 'color-mix(in srgb, var(--input-error-color) 8%, transparent)',
|
|
189
|
+
},
|
|
190
|
+
'&[data-invalid]:focus-within label': {
|
|
191
|
+
color: 'var(--input-error-color)',
|
|
192
|
+
},
|
|
193
|
+
'&[data-invalid][data-variant="outlined"]:focus-within label, &[data-invalid][data-variant="contained"]:focus-within label':
|
|
194
|
+
{
|
|
195
|
+
borderColor: 'var(--input-error-color)',
|
|
196
|
+
boxShadow: '0 0 0 3px rgba(128, 128, 128, 0.15)',
|
|
197
|
+
},
|
|
198
|
+
'&[data-invalid][data-variant="contained"]:focus-within label': {
|
|
199
|
+
background: 'color-mix(in srgb, var(--input-error-color) 12%, transparent)',
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
// Disabled state
|
|
203
|
+
'&[data-disabled] label': {
|
|
204
|
+
color: cssVariableTheme.text.disabled,
|
|
205
|
+
filter: 'grayscale(100%)',
|
|
206
|
+
opacity: '0.5',
|
|
207
|
+
cursor: 'not-allowed',
|
|
208
|
+
},
|
|
209
|
+
'&[data-disabled]:focus-within label': {
|
|
210
|
+
boxShadow: 'none',
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
'& .input-row': {
|
|
214
|
+
display: 'flex',
|
|
215
|
+
alignItems: 'center',
|
|
216
|
+
width: '100%',
|
|
217
|
+
gap: '8px',
|
|
218
|
+
},
|
|
219
|
+
'& input': {
|
|
220
|
+
color: 'inherit',
|
|
221
|
+
border: 'none',
|
|
222
|
+
backgroundColor: 'transparent',
|
|
223
|
+
outline: 'none',
|
|
224
|
+
fontSize: '13px',
|
|
225
|
+
fontWeight: '400',
|
|
226
|
+
width: '100%',
|
|
227
|
+
textOverflow: 'ellipsis',
|
|
228
|
+
padding: '0',
|
|
229
|
+
marginTop: '8px',
|
|
230
|
+
marginBottom: '2px',
|
|
231
|
+
flexGrow: '1',
|
|
232
|
+
lineHeight: '1.5',
|
|
233
|
+
},
|
|
234
|
+
'& .helperText': {
|
|
235
|
+
fontSize: '11px',
|
|
236
|
+
marginTop: '6px',
|
|
237
|
+
opacity: '0.85',
|
|
238
|
+
lineHeight: '1.4',
|
|
239
|
+
},
|
|
240
|
+
'& .startIcon, & .endIcon': {
|
|
241
|
+
display: 'flex',
|
|
242
|
+
alignItems: 'center',
|
|
243
|
+
fontSize: '16px',
|
|
244
|
+
},
|
|
245
|
+
},
|
|
183
246
|
constructed: ({ injector, element }) => {
|
|
184
247
|
if (injector.cachedSingletons.has(FormService)) {
|
|
185
248
|
const input = element.querySelector('input') as HTMLInputElement
|
|
@@ -191,8 +254,22 @@ export const Input = Shade<TextInputProps>({
|
|
|
191
254
|
render: ({ props, injector, useObservable, element }) => {
|
|
192
255
|
const themeProvider = injector.getInstance(ThemeProviderService)
|
|
193
256
|
|
|
257
|
+
// Set data attributes for CSS styling
|
|
258
|
+
if (props.variant) {
|
|
259
|
+
element.setAttribute('data-variant', props.variant)
|
|
260
|
+
} else {
|
|
261
|
+
element.removeAttribute('data-variant')
|
|
262
|
+
}
|
|
263
|
+
if (props.disabled) {
|
|
264
|
+
element.setAttribute('data-disabled', '')
|
|
265
|
+
} else {
|
|
266
|
+
element.removeAttribute('data-disabled')
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Set dynamic color CSS variables (only needs to happen once per render)
|
|
270
|
+
setInputColors({ element, themeProvider, props })
|
|
271
|
+
|
|
194
272
|
const updateState = (newState: TextInputState) => {
|
|
195
|
-
const label = element.querySelector('label') as HTMLLabelElement
|
|
196
273
|
const input = element.querySelector('input') as HTMLInputElement
|
|
197
274
|
|
|
198
275
|
newState.value = input?.value || newState.value
|
|
@@ -214,14 +291,13 @@ export const Input = Shade<TextInputProps>({
|
|
|
214
291
|
|
|
215
292
|
const validationResult = props.getValidationResult?.({ state: newState })
|
|
216
293
|
|
|
294
|
+
// Set data-invalid attribute for CSS styling
|
|
217
295
|
if (validationResult?.isValid === false || newState.validity?.valid === false) {
|
|
218
|
-
element.setAttribute('data-
|
|
296
|
+
element.setAttribute('data-invalid', '')
|
|
219
297
|
} else {
|
|
220
|
-
element.removeAttribute('data-
|
|
298
|
+
element.removeAttribute('data-invalid')
|
|
221
299
|
}
|
|
222
300
|
|
|
223
|
-
attachStyles(label, { style: getLabelStyle({ themeProvider, props, state: newState, validationResult }) })
|
|
224
|
-
|
|
225
301
|
const helper = element.querySelector<HTMLSpanElement>('span.helperText')
|
|
226
302
|
const helperNode =
|
|
227
303
|
(validationResult?.isValid === false && validationResult?.message) ||
|
|
@@ -230,38 +306,16 @@ export const Input = Shade<TextInputProps>({
|
|
|
230
306
|
''
|
|
231
307
|
if (helper) {
|
|
232
308
|
helper.replaceChildren(helperNode)
|
|
233
|
-
attachStyles(helper, {
|
|
234
|
-
style: {
|
|
235
|
-
fontSize: '11px',
|
|
236
|
-
marginTop: '6px',
|
|
237
|
-
opacity: '0.85',
|
|
238
|
-
lineHeight: '1.4',
|
|
239
|
-
},
|
|
240
|
-
})
|
|
241
309
|
}
|
|
242
310
|
|
|
243
311
|
const startIcon = element.querySelector<HTMLSpanElement>('span.startIcon')
|
|
244
312
|
if (startIcon) {
|
|
245
313
|
startIcon.replaceChildren(props.getStartIcon?.({ state: newState, validationResult }) || '')
|
|
246
|
-
attachStyles(startIcon, {
|
|
247
|
-
style: {
|
|
248
|
-
display: 'flex',
|
|
249
|
-
alignItems: 'center',
|
|
250
|
-
fontSize: '16px',
|
|
251
|
-
},
|
|
252
|
-
})
|
|
253
314
|
}
|
|
254
315
|
|
|
255
316
|
const endIcon = element.querySelector<HTMLSpanElement>('span.endIcon')
|
|
256
317
|
if (endIcon) {
|
|
257
318
|
endIcon.replaceChildren(props.getEndIcon?.({ state: newState, validationResult }) || '')
|
|
258
|
-
attachStyles(endIcon, {
|
|
259
|
-
style: {
|
|
260
|
-
display: 'flex',
|
|
261
|
-
alignItems: 'center',
|
|
262
|
-
fontSize: '16px',
|
|
263
|
-
},
|
|
264
|
-
})
|
|
265
319
|
}
|
|
266
320
|
|
|
267
321
|
if (injector.cachedSingletons.has(FormService)) {
|
|
@@ -282,22 +336,11 @@ export const Input = Shade<TextInputProps>({
|
|
|
282
336
|
)
|
|
283
337
|
|
|
284
338
|
return (
|
|
285
|
-
<label {...props.labelProps}
|
|
339
|
+
<label {...props.labelProps}>
|
|
286
340
|
{props.labelTitle}
|
|
287
341
|
|
|
288
|
-
<div
|
|
289
|
-
|
|
290
|
-
display: 'flex',
|
|
291
|
-
alignItems: 'center',
|
|
292
|
-
width: '100%',
|
|
293
|
-
gap: '8px',
|
|
294
|
-
}}
|
|
295
|
-
>
|
|
296
|
-
{props.getStartIcon ? (
|
|
297
|
-
<span className="startIcon" style={{ display: 'flex', alignItems: 'center', fontSize: '16px' }}>
|
|
298
|
-
{props.getStartIcon?.({ state })}
|
|
299
|
-
</span>
|
|
300
|
-
) : null}
|
|
342
|
+
<div className="input-row">
|
|
343
|
+
{props.getStartIcon ? <span className="startIcon">{props.getStartIcon?.({ state })}</span> : null}
|
|
301
344
|
<input
|
|
302
345
|
oninvalid={(ev) => {
|
|
303
346
|
ev.preventDefault()
|
|
@@ -320,41 +363,12 @@ export const Input = Shade<TextInputProps>({
|
|
|
320
363
|
setState({ ...state, focused: false, validity: el.validity })
|
|
321
364
|
}}
|
|
322
365
|
{...props}
|
|
323
|
-
style={
|
|
324
|
-
color: 'inherit',
|
|
325
|
-
border: 'none',
|
|
326
|
-
backgroundColor: 'transparent',
|
|
327
|
-
outline: 'none',
|
|
328
|
-
fontSize: '13px',
|
|
329
|
-
fontWeight: '400',
|
|
330
|
-
width: '100%',
|
|
331
|
-
textOverflow: 'ellipsis',
|
|
332
|
-
padding: '0',
|
|
333
|
-
marginTop: '8px',
|
|
334
|
-
marginBottom: '2px',
|
|
335
|
-
flexGrow: '1',
|
|
336
|
-
lineHeight: '1.5',
|
|
337
|
-
...props.style,
|
|
338
|
-
}}
|
|
366
|
+
style={props.style}
|
|
339
367
|
value={state.value}
|
|
340
368
|
/>
|
|
341
|
-
{props.getEndIcon ? (
|
|
342
|
-
<span className="endIcon" style={{ display: 'flex', alignItems: 'center', fontSize: '16px' }}>
|
|
343
|
-
{props.getEndIcon({ state })}
|
|
344
|
-
</span>
|
|
345
|
-
) : null}
|
|
369
|
+
{props.getEndIcon ? <span className="endIcon">{props.getEndIcon({ state })}</span> : null}
|
|
346
370
|
</div>
|
|
347
|
-
<span
|
|
348
|
-
className="helperText"
|
|
349
|
-
style={{
|
|
350
|
-
fontSize: '11px',
|
|
351
|
-
marginTop: '6px',
|
|
352
|
-
opacity: '0.85',
|
|
353
|
-
lineHeight: '1.4',
|
|
354
|
-
}}
|
|
355
|
-
>
|
|
356
|
-
{props.getHelperText?.({ state })}
|
|
357
|
-
</span>
|
|
371
|
+
<span className="helperText">{props.getHelperText?.({ state })}</span>
|
|
358
372
|
</label>
|
|
359
373
|
)
|
|
360
374
|
},
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { Injector } from '@furystack/inject'
|
|
2
|
+
import { createComponent, initializeShadeRoot } from '@furystack/shades'
|
|
3
|
+
import { sleepAsync } from '@furystack/utils'
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
5
|
+
import { TextArea } from './text-area.js'
|
|
6
|
+
|
|
7
|
+
describe('TextArea', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
document.body.innerHTML = '<div id="root"></div>'
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
document.body.innerHTML = ''
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should render with shadow DOM', async () => {
|
|
17
|
+
const injector = new Injector()
|
|
18
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
19
|
+
|
|
20
|
+
initializeShadeRoot({
|
|
21
|
+
injector,
|
|
22
|
+
rootElement,
|
|
23
|
+
jsxElement: <TextArea />,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
await sleepAsync(50)
|
|
27
|
+
|
|
28
|
+
const textArea = document.querySelector('shade-text-area')
|
|
29
|
+
expect(textArea).not.toBeNull()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should render label with labelTitle', async () => {
|
|
33
|
+
const injector = new Injector()
|
|
34
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
35
|
+
|
|
36
|
+
initializeShadeRoot({
|
|
37
|
+
injector,
|
|
38
|
+
rootElement,
|
|
39
|
+
jsxElement: <TextArea labelTitle="Test Label" />,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
await sleepAsync(50)
|
|
43
|
+
|
|
44
|
+
const textArea = document.querySelector('shade-text-area')
|
|
45
|
+
expect(textArea).not.toBeNull()
|
|
46
|
+
|
|
47
|
+
const label = textArea?.querySelector('label')
|
|
48
|
+
expect(label).not.toBeNull()
|
|
49
|
+
|
|
50
|
+
const span = textArea?.querySelector('span')
|
|
51
|
+
expect(span?.textContent).toBe('Test Label')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should apply labelProps to label element', async () => {
|
|
55
|
+
const injector = new Injector()
|
|
56
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
57
|
+
|
|
58
|
+
initializeShadeRoot({
|
|
59
|
+
injector,
|
|
60
|
+
rootElement,
|
|
61
|
+
jsxElement: <TextArea labelTitle="Test" labelProps={{ className: 'custom-label-class' }} />,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
await sleepAsync(50)
|
|
65
|
+
|
|
66
|
+
const textArea = document.querySelector('shade-text-area')
|
|
67
|
+
const label = textArea?.querySelector('label')
|
|
68
|
+
|
|
69
|
+
expect(label?.className).toBe('custom-label-class')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('should set data-variant attribute for outlined variant', async () => {
|
|
73
|
+
const injector = new Injector()
|
|
74
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
75
|
+
|
|
76
|
+
initializeShadeRoot({
|
|
77
|
+
injector,
|
|
78
|
+
rootElement,
|
|
79
|
+
jsxElement: <TextArea variant="outlined" />,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
await sleepAsync(50)
|
|
83
|
+
|
|
84
|
+
const textArea = document.querySelector('shade-text-area') as HTMLElement
|
|
85
|
+
expect(textArea).not.toBeNull()
|
|
86
|
+
expect(textArea.getAttribute('data-variant')).toBe('outlined')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('should set data-variant attribute for contained variant', async () => {
|
|
90
|
+
const injector = new Injector()
|
|
91
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
92
|
+
|
|
93
|
+
initializeShadeRoot({
|
|
94
|
+
injector,
|
|
95
|
+
rootElement,
|
|
96
|
+
jsxElement: <TextArea variant="contained" />,
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
await sleepAsync(50)
|
|
100
|
+
|
|
101
|
+
const textArea = document.querySelector('shade-text-area') as HTMLElement
|
|
102
|
+
expect(textArea).not.toBeNull()
|
|
103
|
+
expect(textArea.getAttribute('data-variant')).toBe('contained')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('should not set data-variant attribute when no variant is provided', async () => {
|
|
107
|
+
const injector = new Injector()
|
|
108
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
109
|
+
|
|
110
|
+
initializeShadeRoot({
|
|
111
|
+
injector,
|
|
112
|
+
rootElement,
|
|
113
|
+
jsxElement: <TextArea />,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
await sleepAsync(50)
|
|
117
|
+
|
|
118
|
+
const textArea = document.querySelector('shade-text-area') as HTMLElement
|
|
119
|
+
expect(textArea).not.toBeNull()
|
|
120
|
+
expect(textArea.hasAttribute('data-variant')).toBe(false)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('should set data-disabled attribute when disabled', async () => {
|
|
124
|
+
const injector = new Injector()
|
|
125
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
126
|
+
|
|
127
|
+
initializeShadeRoot({
|
|
128
|
+
injector,
|
|
129
|
+
rootElement,
|
|
130
|
+
jsxElement: <TextArea disabled />,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
await sleepAsync(50)
|
|
134
|
+
|
|
135
|
+
const textArea = document.querySelector('shade-text-area') as HTMLElement
|
|
136
|
+
expect(textArea).not.toBeNull()
|
|
137
|
+
expect(textArea.hasAttribute('data-disabled')).toBe(true)
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('should not set data-disabled attribute when not disabled', async () => {
|
|
141
|
+
const injector = new Injector()
|
|
142
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
143
|
+
|
|
144
|
+
initializeShadeRoot({
|
|
145
|
+
injector,
|
|
146
|
+
rootElement,
|
|
147
|
+
jsxElement: <TextArea disabled={false} />,
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
await sleepAsync(50)
|
|
151
|
+
|
|
152
|
+
const textArea = document.querySelector('shade-text-area') as HTMLElement
|
|
153
|
+
expect(textArea).not.toBeNull()
|
|
154
|
+
expect(textArea.hasAttribute('data-disabled')).toBe(false)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('should render value in contentEditable div', async () => {
|
|
158
|
+
const injector = new Injector()
|
|
159
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
160
|
+
|
|
161
|
+
initializeShadeRoot({
|
|
162
|
+
injector,
|
|
163
|
+
rootElement,
|
|
164
|
+
jsxElement: <TextArea value="Test content" />,
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
await sleepAsync(50)
|
|
168
|
+
|
|
169
|
+
const textArea = document.querySelector('shade-text-area')
|
|
170
|
+
const contentDiv = textArea?.querySelector('.textarea-content')
|
|
171
|
+
|
|
172
|
+
expect(contentDiv).not.toBeNull()
|
|
173
|
+
expect(contentDiv?.textContent).toBe('Test content')
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('should have contentEditable true when not readOnly or disabled', async () => {
|
|
177
|
+
const injector = new Injector()
|
|
178
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
179
|
+
|
|
180
|
+
initializeShadeRoot({
|
|
181
|
+
injector,
|
|
182
|
+
rootElement,
|
|
183
|
+
jsxElement: <TextArea />,
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
await sleepAsync(50)
|
|
187
|
+
|
|
188
|
+
const textArea = document.querySelector('shade-text-area')
|
|
189
|
+
const contentDiv = textArea?.querySelector('.textarea-content') as HTMLElement
|
|
190
|
+
|
|
191
|
+
expect(contentDiv?.contentEditable).toBe('true')
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('should have contentEditable inherit when readOnly is true', async () => {
|
|
195
|
+
const injector = new Injector()
|
|
196
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
197
|
+
|
|
198
|
+
initializeShadeRoot({
|
|
199
|
+
injector,
|
|
200
|
+
rootElement,
|
|
201
|
+
jsxElement: <TextArea readOnly />,
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
await sleepAsync(50)
|
|
205
|
+
|
|
206
|
+
const textArea = document.querySelector('shade-text-area')
|
|
207
|
+
const contentDiv = textArea?.querySelector('.textarea-content') as HTMLElement
|
|
208
|
+
|
|
209
|
+
expect(contentDiv?.contentEditable).toBe('inherit')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('should have contentEditable inherit when disabled is true', async () => {
|
|
213
|
+
const injector = new Injector()
|
|
214
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
215
|
+
|
|
216
|
+
initializeShadeRoot({
|
|
217
|
+
injector,
|
|
218
|
+
rootElement,
|
|
219
|
+
jsxElement: <TextArea disabled />,
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
await sleepAsync(50)
|
|
223
|
+
|
|
224
|
+
const textArea = document.querySelector('shade-text-area')
|
|
225
|
+
const contentDiv = textArea?.querySelector('.textarea-content') as HTMLElement
|
|
226
|
+
|
|
227
|
+
expect(contentDiv?.contentEditable).toBe('inherit')
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('should apply custom style to content div', async () => {
|
|
231
|
+
const injector = new Injector()
|
|
232
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
233
|
+
|
|
234
|
+
initializeShadeRoot({
|
|
235
|
+
injector,
|
|
236
|
+
rootElement,
|
|
237
|
+
jsxElement: <TextArea style={{ color: 'red' }} />,
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
await sleepAsync(50)
|
|
241
|
+
|
|
242
|
+
const textArea = document.querySelector('shade-text-area')
|
|
243
|
+
const contentDiv = textArea?.querySelector('.textarea-content') as HTMLElement
|
|
244
|
+
|
|
245
|
+
expect(contentDiv?.style.color).toBe('red')
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
it('should apply custom style to label element', async () => {
|
|
249
|
+
const injector = new Injector()
|
|
250
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
251
|
+
|
|
252
|
+
initializeShadeRoot({
|
|
253
|
+
injector,
|
|
254
|
+
rootElement,
|
|
255
|
+
jsxElement: <TextArea labelProps={{ style: { backgroundColor: 'blue' } }} />,
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
await sleepAsync(50)
|
|
259
|
+
|
|
260
|
+
const textArea = document.querySelector('shade-text-area')
|
|
261
|
+
const label = textArea?.querySelector('label') as HTMLElement
|
|
262
|
+
|
|
263
|
+
expect(label?.style.backgroundColor).toBe('blue')
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
it('should have correct CSS styles applied', async () => {
|
|
267
|
+
const injector = new Injector()
|
|
268
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
269
|
+
|
|
270
|
+
initializeShadeRoot({
|
|
271
|
+
injector,
|
|
272
|
+
rootElement,
|
|
273
|
+
jsxElement: <TextArea />,
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
await sleepAsync(50)
|
|
277
|
+
|
|
278
|
+
const textArea = document.querySelector('shade-text-area') as HTMLElement
|
|
279
|
+
expect(textArea).not.toBeNull()
|
|
280
|
+
|
|
281
|
+
const computedStyle = window.getComputedStyle(textArea)
|
|
282
|
+
expect(computedStyle.display).toBe('block')
|
|
283
|
+
expect(computedStyle.marginBottom).toBe('1em')
|
|
284
|
+
})
|
|
285
|
+
})
|