Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3
This commit is contained in:
commit
461eb8752d
15 changed files with 217 additions and 127 deletions
|
@ -3,6 +3,12 @@
|
|||
class="ComponentPreview"
|
||||
:class="{ '-shadow-controls': shadowControl }"
|
||||
>
|
||||
<!-- eslint-disable vue/no-v-html vue/no-v-text-v-html-on-component -->
|
||||
<component
|
||||
:is="'style'"
|
||||
v-html="previewCss"
|
||||
/>
|
||||
<!-- eslint-enable vue/no-v-html vue/no-v-text-v-html-on-component -->
|
||||
<label
|
||||
v-show="shadowControl"
|
||||
class="header"
|
||||
|
@ -11,7 +17,7 @@
|
|||
{{ $t('settings.style.shadows.offset') }}
|
||||
</label>
|
||||
<input
|
||||
v-show="shadowControl"
|
||||
v-show="shadowControl && !hideControls"
|
||||
:value="shadow?.y"
|
||||
:disabled="disabled"
|
||||
:class="{ disabled }"
|
||||
|
@ -20,7 +26,7 @@
|
|||
@input="e => updateProperty('y', e.target.value)"
|
||||
>
|
||||
<input
|
||||
v-show="shadowControl"
|
||||
v-show="shadowControl && !hideControls"
|
||||
:value="shadow?.y"
|
||||
:disabled="disabled"
|
||||
:class="{ disabled }"
|
||||
|
@ -41,9 +47,14 @@
|
|||
>
|
||||
{{ $t('settings.style.themes3.editor.test_string') }}
|
||||
</div>
|
||||
<div v-if="invalid" class="invalid-container">
|
||||
<div class="alert error invalid-label">
|
||||
{{ $t('settings.style.themes3.editor.invalid') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
v-show="shadowControl"
|
||||
v-show="shadowControl && !hideControls"
|
||||
:value="shadow?.x"
|
||||
:disabled="disabled"
|
||||
:class="{ disabled }"
|
||||
|
@ -52,7 +63,7 @@
|
|||
@input="e => updateProperty('x', e.target.value)"
|
||||
>
|
||||
<input
|
||||
v-show="shadowControl"
|
||||
v-show="shadowControl && !hideControls"
|
||||
:value="shadow?.x"
|
||||
:disabled="disabled"
|
||||
:class="{ disabled }"
|
||||
|
@ -85,7 +96,9 @@ export default {
|
|||
'shadowControl',
|
||||
'previewClass',
|
||||
'previewStyle',
|
||||
'disabled'
|
||||
'previewCss',
|
||||
'disabled',
|
||||
'invalid'
|
||||
],
|
||||
emits: ['update:shadow'],
|
||||
data () {
|
||||
|
@ -93,9 +106,14 @@ export default {
|
|||
lightGrid: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hideControls () {
|
||||
return typeof this.shadow === 'string'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateProperty (axis, value) {
|
||||
this.$emit('update:shadow', { axis, value })
|
||||
this.$emit('update:shadow', { axis, value: Number(value) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +139,22 @@ export default {
|
|||
line-height: 2;
|
||||
}
|
||||
|
||||
.invalid-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
background-color: rgba(100 0 0 / 50%);
|
||||
|
||||
.alert {
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.input-light-grid {
|
||||
grid-area: options;
|
||||
justify-self: center;
|
||||
|
@ -170,6 +204,7 @@ export default {
|
|||
--__grid-color2-disabled: rgba(255 255 255 / 20%);
|
||||
}
|
||||
|
||||
position: relative;
|
||||
grid-area: preview;
|
||||
aspect-ratio: 1;
|
||||
display: flex;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export default {
|
||||
name: 'Modals',
|
||||
selector: '.modal-view',
|
||||
selector: ['.modal-view', '#modal', '.shout-panel'],
|
||||
lazy: true,
|
||||
notEditable: true,
|
||||
validInnerComponents: [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export default {
|
||||
name: 'Scrollbar',
|
||||
selector: '::-webkit-scrollbar',
|
||||
selector: ['::-webkit-scrollbar-button', '::-webkit-scrollbar-thumb', '::-webkit-resizer'],
|
||||
notEditable: true, // for now
|
||||
defaultRules: [
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
>
|
||||
<button
|
||||
class="btn button-default"
|
||||
:disabled="disabled || shadowsAreNull"
|
||||
:disabled="disabled"
|
||||
@click="add"
|
||||
>
|
||||
<FAIcon
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
getScopedVersion
|
||||
} from 'src/services/theme_data/css_utils.js'
|
||||
import { serializeShadow, serialize } from 'src/services/theme_data/iss_serializer.js'
|
||||
import { parseShadow, deserialize } from 'src/services/theme_data/iss_deserializer.js'
|
||||
import { deserializeShadow, deserialize } from 'src/services/theme_data/iss_deserializer.js'
|
||||
import {
|
||||
rgb2hex,
|
||||
hex2rgb,
|
||||
|
@ -371,7 +371,11 @@ export default {
|
|||
return shadow
|
||||
}
|
||||
if (typeof shadow === 'string') {
|
||||
return parseShadow(shadow)
|
||||
try {
|
||||
return deserializeShadow(shadow)
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
@ -580,6 +584,7 @@ export default {
|
|||
|
||||
const selectedVirtualDirectiveId = ref(0)
|
||||
exports.selectedVirtualDirectiveId = selectedVirtualDirectiveId
|
||||
|
||||
const selectedVirtualDirective = computed({
|
||||
get () {
|
||||
return virtualDirectives[selectedVirtualDirectiveId.value]
|
||||
|
@ -589,6 +594,7 @@ export default {
|
|||
}
|
||||
})
|
||||
exports.selectedVirtualDirective = selectedVirtualDirective
|
||||
|
||||
exports.selectedVirtualDirectiveValType = computed({
|
||||
get () {
|
||||
return virtualDirectives[selectedVirtualDirectiveId.value].valType
|
||||
|
@ -607,35 +613,56 @@ export default {
|
|||
}
|
||||
}
|
||||
})
|
||||
exports.selectedVirtualDirectiveParsed = computed({
|
||||
get () {
|
||||
switch (selectedVirtualDirective.value.valType) {
|
||||
|
||||
const draftVirtualDirectiveValid = ref(true)
|
||||
const draftVirtualDirective = ref({})
|
||||
exports.draftVirtualDirective = draftVirtualDirective
|
||||
|
||||
watch(
|
||||
selectedVirtualDirective,
|
||||
(directive) => {
|
||||
switch (directive.valType) {
|
||||
case 'shadow': {
|
||||
const directiveValue = selectedVirtualDirective.value.value
|
||||
if (Array.isArray(directiveValue)) {
|
||||
return normalizeShadows(directiveValue)
|
||||
if (Array.isArray(directive.value)) {
|
||||
draftVirtualDirective.value = normalizeShadows(directive.value)
|
||||
} else {
|
||||
const splitShadow = directiveValue.split(/,/g).map(x => x.trim())
|
||||
return normalizeShadows(splitShadow)
|
||||
const splitShadow = directive.value.split(/,/g).map(x => x.trim())
|
||||
draftVirtualDirective.value = normalizeShadows(splitShadow)
|
||||
}
|
||||
}
|
||||
case 'color':
|
||||
return selectedVirtualDirective.value.value
|
||||
default:
|
||||
return selectedVirtualDirective.value.value
|
||||
}
|
||||
},
|
||||
set (value) {
|
||||
switch (selectedVirtualDirective.value.valType) {
|
||||
case 'shadow': {
|
||||
virtualDirectives[selectedVirtualDirectiveId.value].value = value.map(x => serializeShadow(x)).join(', ')
|
||||
break
|
||||
}
|
||||
case 'color':
|
||||
draftVirtualDirective.value = directive.value
|
||||
break
|
||||
default:
|
||||
virtualDirectives[selectedVirtualDirectiveId.value].value = value
|
||||
draftVirtualDirective.value = directive.value
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
draftVirtualDirective,
|
||||
(directive) => {
|
||||
try {
|
||||
switch (selectedVirtualDirective.value.valType) {
|
||||
case 'shadow': {
|
||||
virtualDirectives[selectedVirtualDirectiveId.value].value =
|
||||
directive.map(x => serializeShadow(x)).join(', ')
|
||||
break
|
||||
}
|
||||
default:
|
||||
virtualDirectives[selectedVirtualDirectiveId.value].value = directive
|
||||
}
|
||||
draftVirtualDirectiveValid.value = true
|
||||
} catch (e) {
|
||||
console.error('Invalid virtual directive value', e)
|
||||
draftVirtualDirectiveValid.value = false
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
exports.getNewVirtualDirective = () => ({
|
||||
name: 'newDirective',
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
:shadow-control="isShadowTabOpen"
|
||||
:preview-class="previewClass"
|
||||
:preview-style="editorHintStyle"
|
||||
:preview-css="previewCss"
|
||||
:disabled="!editedSubShadow && typeof editedShadow !== 'string'"
|
||||
:shadow="editedSubShadow"
|
||||
@update:shadow="({ axis, value }) => updateSubShadow(axis, value)"
|
||||
|
@ -285,7 +286,7 @@
|
|||
:disabled="!isShadowPresent"
|
||||
:no-preview="true"
|
||||
:compact="true"
|
||||
:separate-inset="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'"
|
||||
:static-vars="selectedPalette"
|
||||
@subShadowSelected="onSubShadow"
|
||||
/>
|
||||
</div>
|
||||
|
@ -408,14 +409,14 @@
|
|||
</div>
|
||||
<ShadowControl
|
||||
v-if="selectedVirtualDirectiveValType === 'shadow'"
|
||||
v-model="selectedVirtualDirectiveParsed"
|
||||
:computeColor="computeColor"
|
||||
v-model="draftVirtualDirective"
|
||||
:static-vars="selectedPalette"
|
||||
:compact="true"
|
||||
/>
|
||||
<ColorInput
|
||||
v-if="selectedVirtualDirectiveValType === 'color'"
|
||||
v-model="selectedVirtualDirectiveParsed"
|
||||
:fallback="computeColor(selectedVirtualDirectiveParsed)"
|
||||
v-model="draftVirtualDirective"
|
||||
:fallback="computeColor(draftVirtualDirective)"
|
||||
:label="$t('settings.style.themes3.editor.variables.virtual_color')"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -957,6 +957,7 @@
|
|||
v-model="currentShadow"
|
||||
:separate-inset="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'"
|
||||
:fallback="currentShadowFallback"
|
||||
:static-vars="previewTheme.colors"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
@ -5,9 +5,13 @@ import SelectMotion from 'src/components/select/select_motion.vue'
|
|||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||
import Popover from 'src/components/popover/popover.vue'
|
||||
import ComponentPreview from 'src/components/component_preview/component_preview.vue'
|
||||
import { getCssShadow, getCssShadowFilter } from '../../services/theme_data/theme_data.service.js'
|
||||
import { rgb2hex } from 'src/services/color_convert/color_convert.js'
|
||||
import { serializeShadow } from 'src/services/theme_data/iss_serializer.js'
|
||||
import { deserializeShadow } from 'src/services/theme_data/iss_deserializer.js'
|
||||
import { getCssShadow, getCssShadowFilter } from 'src/services/theme_data/css_utils.js'
|
||||
import { findShadow, findColor } from 'src/services/theme_data/theme_data_3.service.js'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { throttle } from 'lodash'
|
||||
import { throttle, flattenDeep } from 'lodash'
|
||||
import {
|
||||
faTimes,
|
||||
faChevronDown,
|
||||
|
@ -46,13 +50,14 @@ export default {
|
|||
'separateInset',
|
||||
'noPreview',
|
||||
'disabled',
|
||||
'computeColor',
|
||||
'staticVars',
|
||||
'compact'
|
||||
],
|
||||
emits: ['update:modelValue', 'subShadowSelected'],
|
||||
data () {
|
||||
return {
|
||||
selectedId: 0
|
||||
selectedId: 0,
|
||||
invalid: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
@ -97,7 +102,7 @@ export default {
|
|||
}
|
||||
},
|
||||
present () {
|
||||
return this.selected != null && !this.usingFallback
|
||||
return this.selected != null && this.modelValue != null
|
||||
},
|
||||
shadowsAreNull () {
|
||||
return this.modelValue == null
|
||||
|
@ -105,31 +110,38 @@ export default {
|
|||
currentFallback () {
|
||||
return this.fallback?.[this.selectedId]
|
||||
},
|
||||
usingFallback () {
|
||||
return this.modelValue == null
|
||||
},
|
||||
getFallback () {
|
||||
if (typeof this.computeColor === 'function' && this.selected?.color) {
|
||||
return this.computeColor(this.selected.color)
|
||||
getColorFallback () {
|
||||
if (this.staticVars && this.selected?.color) {
|
||||
const computedColor = findColor(this.selected.color, { dynamicVars: {}, staticVars: this.staticVars }, true)
|
||||
if (computedColor) return rgb2hex(computedColor)
|
||||
return null
|
||||
} else {
|
||||
return this.currentFallback?.color
|
||||
}
|
||||
},
|
||||
style () {
|
||||
try {
|
||||
let result
|
||||
const serialized = this.cValue.map(x => serializeShadow(x)).join(',')
|
||||
deserializeShadow(serialized) // validate
|
||||
const expandedShadow = flattenDeep(findShadow(this.cValue, { dynamicVars: {}, staticVars: this.staticVars }))
|
||||
const fixedShadows = expandedShadow.map(x => ({ ...x, color: console.log(x) || rgb2hex(x.color) }))
|
||||
|
||||
if (this.separateInset) {
|
||||
return {
|
||||
filter: getCssShadowFilter(this.cValue),
|
||||
boxShadow: getCssShadow(this.cValue, true)
|
||||
result = {
|
||||
filter: getCssShadowFilter(fixedShadows),
|
||||
boxShadow: getCssShadow(fixedShadows, true)
|
||||
}
|
||||
} else {
|
||||
result = {
|
||||
boxShadow: getCssShadow(fixedShadows)
|
||||
}
|
||||
}
|
||||
return {
|
||||
boxShadow: getCssShadow(this.cValue)
|
||||
}
|
||||
this.invalid = false
|
||||
return result
|
||||
} catch (e) {
|
||||
return {
|
||||
border: '1px solid red'
|
||||
}
|
||||
console.error('Invalid shadow', e)
|
||||
this.invalid = true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
>
|
||||
<ComponentPreview
|
||||
v-if="!noPreview"
|
||||
:invalid="invalid"
|
||||
class="shadow-preview"
|
||||
:shadow-control="true"
|
||||
:shadow="selected"
|
||||
:preview-style="style"
|
||||
:disabled="disabled || !present"
|
||||
@update:shadow="({ axis, value }) => updateProperty(axis, value)"
|
||||
/>
|
||||
|
@ -165,7 +167,7 @@
|
|||
:model-value="selected?.color"
|
||||
:disabled="disabled || !present"
|
||||
:label="$t('settings.style.common.color')"
|
||||
:fallback="getFallback"
|
||||
:fallback="getColorFallback"
|
||||
:show-optional-tickbox="false"
|
||||
name="shadow"
|
||||
@update:modelValue="e => updateProperty('color', e)"
|
||||
|
|
|
@ -793,8 +793,10 @@
|
|||
"text_color": "Text color",
|
||||
"icon_color": "Icon color",
|
||||
"link_color": "Link color",
|
||||
"border_color": "Border color",
|
||||
"include_in_rule": "Add to rule",
|
||||
"test_string": "TEST",
|
||||
"invalid": "Invalid",
|
||||
"refresh_preview": "Refresh preview",
|
||||
"apply_preview": "Apply",
|
||||
"text_auto": {
|
||||
|
|
|
@ -56,22 +56,7 @@ export const generateTheme = (inputRuleset, callbacks, debug) => {
|
|||
|
||||
getCssRules(themes3.eager, debug).forEach(rule => {
|
||||
// Hacks to support multiple selectors on same component
|
||||
if (rule.match(/::-webkit-scrollbar-button/)) {
|
||||
const parts = rule.split(/[{}]/g)
|
||||
const newRule = [
|
||||
parts[0],
|
||||
', ',
|
||||
parts[0].replace(/button/, 'thumb'),
|
||||
', ',
|
||||
parts[0].replace(/scrollbar-button/, 'resizer'),
|
||||
' {',
|
||||
parts[1],
|
||||
'}'
|
||||
].join('')
|
||||
onNewRule(newRule, false)
|
||||
} else {
|
||||
onNewRule(rule, false)
|
||||
}
|
||||
onNewRule(rule, false)
|
||||
})
|
||||
onEagerFinished()
|
||||
|
||||
|
@ -85,22 +70,7 @@ export const generateTheme = (inputRuleset, callbacks, debug) => {
|
|||
const chunk = chunks[counter]
|
||||
Promise.all(chunk.map(x => x())).then(result => {
|
||||
getCssRules(result.filter(x => x), debug).forEach(rule => {
|
||||
if (rule.match(/\.modal-view/)) {
|
||||
const parts = rule.split(/[{}]/g)
|
||||
const newRule = [
|
||||
parts[0],
|
||||
', ',
|
||||
parts[0].replace(/\.modal-view/, '#modal'),
|
||||
', ',
|
||||
parts[0].replace(/\.modal-view/, '.shout-panel'),
|
||||
' {',
|
||||
parts[1],
|
||||
'}'
|
||||
].join('')
|
||||
onNewRule(newRule, true)
|
||||
} else {
|
||||
onNewRule(rule, true)
|
||||
}
|
||||
onNewRule(rule, true)
|
||||
})
|
||||
// const t1 = performance.now()
|
||||
// console.debug('Chunk ' + counter + ' took ' + (t1 - t0) + 'ms')
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { flattenDeep } from 'lodash'
|
||||
|
||||
export const parseShadow = string => {
|
||||
const modes = ['_full', 'inset', 'x', 'y', 'blur', 'spread', 'color', 'alpha']
|
||||
export const deserializeShadow = string => {
|
||||
const modes = ['_full', 'inset', 'x', 'y', 'blur', 'spread', 'color', 'alpha', 'name']
|
||||
const regexPrep = [
|
||||
// inset keyword (optional)
|
||||
'^(?:(inset)\\s+)?',
|
||||
'^',
|
||||
'(?:(inset)\\s+)?',
|
||||
// x
|
||||
'(?:(-?[0-9]+(?:\\.[0-9]+)?)\\s+)',
|
||||
// y
|
||||
|
@ -16,7 +17,10 @@ export const parseShadow = string => {
|
|||
// either hex, variable or function
|
||||
'(#[0-9a-f]{6}|--[a-z\\-_]+|\\$[a-z\\-()_]+)',
|
||||
// opacity (optional)
|
||||
'(?:\\s+\\/\\s+([0-9]+(?:\\.[0-9]+)?)\\s*)?$'
|
||||
'(?:\\s+\\/\\s+([0-9]+(?:\\.[0-9]+)?)\\s*)?',
|
||||
// name
|
||||
'(?:\\s+#(\\w+)\\s*)?',
|
||||
'$'
|
||||
].join('')
|
||||
const regex = new RegExp(regexPrep, 'gis') // global, (stable) indices, single-string
|
||||
const result = regex.exec(string)
|
||||
|
@ -24,11 +28,11 @@ export const parseShadow = string => {
|
|||
if (string.startsWith('$') || string.startsWith('--')) {
|
||||
return string
|
||||
} else {
|
||||
throw new Error(`Invalid shadow definition: ${string}`)
|
||||
throw new Error(`Invalid shadow definition: '${string}'`)
|
||||
}
|
||||
} else {
|
||||
const numeric = new Set(['x', 'y', 'blur', 'spread', 'alpha'])
|
||||
const { x, y, blur, spread, alpha, inset, color } = Object.fromEntries(modes.map((mode, i) => {
|
||||
const { x, y, blur, spread, alpha, inset, color, name } = Object.fromEntries(modes.map((mode, i) => {
|
||||
if (numeric.has(mode)) {
|
||||
const number = Number(result[i])
|
||||
if (Number.isNaN(number)) {
|
||||
|
@ -43,7 +47,7 @@ export const parseShadow = string => {
|
|||
}
|
||||
}).filter(([k, v]) => v !== false).slice(1))
|
||||
|
||||
return { x, y, blur, spread, color, alpha, inset }
|
||||
return { x, y, blur, spread, color, alpha, inset, name }
|
||||
}
|
||||
}
|
||||
// this works nearly the same as HTML tree converter
|
||||
|
@ -150,7 +154,7 @@ export const deserialize = (input) => {
|
|||
if (realValue === 'none') {
|
||||
realValue = []
|
||||
} else {
|
||||
realValue = value.split(',').map(v => parseShadow(v.trim()))
|
||||
realValue = value.split(',').map(v => deserializeShadow(v.trim()))
|
||||
}
|
||||
} if (!Number.isNaN(Number(value))) {
|
||||
realValue = Number(value)
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import { unroll } from './iss_utils.js'
|
||||
import { deserializeShadow } from './iss_deserializer.js'
|
||||
|
||||
export const serializeShadow = (s, throwOnInvalid) => {
|
||||
if (typeof s === 'object') {
|
||||
return `${s.inset ? 'inset ' : ''}${s.x} ${s.y} ${s.blur} ${s.spread} ${s.color} / ${s.alpha}`
|
||||
const inset = s.inset ? 'inset ' : ''
|
||||
const name = s.name ? ` #${s.name} ` : ''
|
||||
const result = `${inset}${s.x} ${s.y} ${s.blur} ${s.spread} ${s.color} / ${s.alpha}${name}`
|
||||
deserializeShadow(result) // Verify that output is valid and parseable
|
||||
return result
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
|
|
|
@ -56,43 +56,74 @@ export const getAllPossibleCombinations = (array) => {
|
|||
*
|
||||
* @returns {String} CSS selector (or path)
|
||||
*/
|
||||
export const genericRuleToSelector = components => (rule, ignoreOutOfTreeSelector, isParent) => {
|
||||
export const genericRuleToSelector = components => (rule, ignoreOutOfTreeSelector, liteMode, children) => {
|
||||
const isParent = !!children
|
||||
if (!rule && !isParent) return null
|
||||
const component = components[rule.component]
|
||||
const { states = {}, variants = {}, selector, outOfTreeSelector } = component
|
||||
const { states = {}, variants = {}, outOfTreeSelector } = component
|
||||
|
||||
const applicableStates = ((rule.state || []).filter(x => x !== 'normal')).map(state => states[state])
|
||||
const expand = (array = [], subArray = []) => {
|
||||
if (array.length === 0) return subArray.map(x => [x])
|
||||
if (subArray.length === 0) return array.map(x => [x])
|
||||
return array.map(a => {
|
||||
return subArray.map(b => [a, b])
|
||||
}).flat()
|
||||
}
|
||||
|
||||
let componentSelectors = Array.isArray(component.selector) ? component.selector : [component.selector]
|
||||
if (ignoreOutOfTreeSelector || liteMode) componentSelectors = [componentSelectors[0]]
|
||||
componentSelectors = componentSelectors.map(selector => {
|
||||
if (selector === ':root') {
|
||||
return ''
|
||||
} else if (isParent) {
|
||||
return selector
|
||||
} else {
|
||||
if (outOfTreeSelector && !ignoreOutOfTreeSelector) return outOfTreeSelector
|
||||
return selector
|
||||
}
|
||||
})
|
||||
|
||||
const applicableVariantName = (rule.variant || 'normal')
|
||||
let applicableVariant = ''
|
||||
let variantSelectors = null
|
||||
if (applicableVariantName !== 'normal') {
|
||||
applicableVariant = variants[applicableVariantName]
|
||||
variantSelectors = variants[applicableVariantName]
|
||||
} else {
|
||||
applicableVariant = variants?.normal ?? ''
|
||||
variantSelectors = variants?.normal ?? ''
|
||||
}
|
||||
variantSelectors = Array.isArray(variantSelectors) ? variantSelectors : [variantSelectors]
|
||||
if (ignoreOutOfTreeSelector || liteMode) variantSelectors = [variantSelectors[0]]
|
||||
|
||||
let realSelector
|
||||
if (selector === ':root') {
|
||||
realSelector = ''
|
||||
} else if (isParent) {
|
||||
realSelector = selector
|
||||
} else {
|
||||
if (outOfTreeSelector && !ignoreOutOfTreeSelector) realSelector = outOfTreeSelector
|
||||
else realSelector = selector
|
||||
}
|
||||
const applicableStates = (rule.state || []).filter(x => x !== 'normal')
|
||||
// const applicableStates = (rule.state || [])
|
||||
const statesSelectors = applicableStates.map(state => {
|
||||
const selector = states[state] || ''
|
||||
let arraySelector = Array.isArray(selector) ? selector : [selector]
|
||||
if (ignoreOutOfTreeSelector || liteMode) arraySelector = [arraySelector[0]]
|
||||
arraySelector
|
||||
.sort((a, b) => {
|
||||
if (a.startsWith(':')) return 1
|
||||
if (/^[a-z]/.exec(a)) return -1
|
||||
else return 0
|
||||
})
|
||||
.join('')
|
||||
return arraySelector
|
||||
})
|
||||
|
||||
const selectors = [realSelector, applicableVariant, ...applicableStates]
|
||||
.sort((a, b) => {
|
||||
if (a.startsWith(':')) return 1
|
||||
if (/^[a-z]/.exec(a)) return -1
|
||||
else return 0
|
||||
})
|
||||
.join('')
|
||||
const statesSelectorsFlat = statesSelectors.reduce((acc, s) => {
|
||||
return expand(acc, s).map(st => st.join(''))
|
||||
}, [])
|
||||
|
||||
const componentVariant = expand(componentSelectors, variantSelectors).map(cv => cv.join(''))
|
||||
const componentVariantStates = expand(componentVariant, statesSelectorsFlat).map(cvs => cvs.join(''))
|
||||
const selectors = expand(componentVariantStates, children).map(cvsc => cvsc.join(' '))
|
||||
/*
|
||||
*/
|
||||
|
||||
if (rule.parent) {
|
||||
return (genericRuleToSelector(components)(rule.parent, ignoreOutOfTreeSelector, true) + ' ' + selectors).trim()
|
||||
return genericRuleToSelector(components)(rule.parent, ignoreOutOfTreeSelector, liteMode, selectors)
|
||||
}
|
||||
return selectors.trim()
|
||||
|
||||
return selectors.join(', ').trim()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@ import {
|
|||
normalizeCombination,
|
||||
findRules
|
||||
} from './iss_utils.js'
|
||||
import { parseShadow } from './iss_deserializer.js'
|
||||
import { deserializeShadow } from './iss_deserializer.js'
|
||||
|
||||
// Ensuring the order of components
|
||||
const components = {
|
||||
|
@ -37,7 +37,7 @@ const components = {
|
|||
ChatMessage: null
|
||||
}
|
||||
|
||||
const findShadow = (shadows, { dynamicVars, staticVars }) => {
|
||||
export const findShadow = (shadows, { dynamicVars, staticVars }) => {
|
||||
return (shadows || []).map(shadow => {
|
||||
let targetShadow
|
||||
if (typeof shadow === 'string') {
|
||||
|
@ -48,7 +48,7 @@ const findShadow = (shadows, { dynamicVars, staticVars }) => {
|
|||
const variableSlot = shadow.substring(2)
|
||||
return findShadow(staticVars[variableSlot], { dynamicVars, staticVars })
|
||||
} else {
|
||||
targetShadow = parseShadow(shadow)
|
||||
targetShadow = deserializeShadow(shadow)
|
||||
}
|
||||
} else {
|
||||
targetShadow = shadow
|
||||
|
|
Loading…
Add table
Reference in a new issue