Skip to content

Commit

Permalink
rename condition to operation for flexibility with future use cases
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexVipond committed May 18, 2021
1 parent 253dc3e commit 53535f6
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 86 deletions.
36 changes: 17 additions & 19 deletions src/interface/CssSelectorBuilder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,8 @@
</transition>
</button>
</section>
<section class="w-full max-w-xl flex flex-col gap-4">
<section class="px-6 py-8 rounded-md shadow-lg bg-denim-800 text-denim-200">
<FormConditions :isTopLevel="true" v-model="conditions" />
</section>
<section class="w-full max-w-xl">
<FormOperations :isTopLevel="true" v-model="operations" />
</section>
</main>
<footer class="flex flex-col gap-6 bg-denim-1200 px-6 py-8 text-denim-300">
Expand Down Expand Up @@ -107,13 +105,13 @@ import {
import { useCopyable } from '@baleada/vue-composition'
import { CheckIcon, ClipboardCopyIcon } from '@heroicons/vue/solid'
import { toSelector } from './toSelector'
import type { Condition } from './toSelector'
import FormConditions from './components/FormConditions.vue'
import type { Operation } from './toSelector'
import FormOperations from './components/FormOperations.vue'
import PopoverHelp from './components/PopoverHelp.vue'
export default defineComponent({
components: {
FormConditions,
FormOperations,
SimpleTwitter,
SimpleGitHub,
SimpleNPM,
Expand All @@ -122,42 +120,42 @@ export default defineComponent({
ClipboardCopyIcon,
},
setup () {
const conditions = ref<Condition[]>([]),
selector = computed(() => toSelector(conditions.value)),
const operations = ref<Operation[]>([]),
selector = computed(() => toSelector(operations.value)),
clipboard = { text: '' },
copyable = useCopyable(selector.value, { clipboard })
watch(selector, async () => copyable.value.string = selector.value)
onMounted(() => {
const urlConditions = new URL(window.location.toString()).searchParams.get('conditions')
if (urlConditions) {
conditions.value = withoutNull(JSON.parse(urlConditions))
const urlOperations = new URL(window.location.toString()).searchParams.get('operations')
if (urlOperations) {
operations.value = withoutNull(JSON.parse(urlOperations))
}
})
watch(
conditions,
operations,
() => {
const url = new URL(window.origin)
url.searchParams.set('conditions', JSON.stringify(conditions.value))
url.searchParams.set('operations', JSON.stringify(operations.value))
history.pushState({}, document.title, url.toString())
}
)
return {
conditions,
operations,
selector,
copyable,
}
}
})
function withoutNull (parsedConditions: Record<any, any>): Condition[] {
return parsedConditions.map(condition => ({
...condition,
args: condition.args.map(arg => {
function withoutNull (parsedOperations: Record<any, any>): Operation[] {
return parsedOperations.map(operation => ({
...operation,
args: operation.args.map(arg => {
if (arg === null) {
return undefined
}
Expand Down
8 changes: 1 addition & 7 deletions src/interface/components/FormArg.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@
v-model="arg"
:required="required"
/>
<div
v-if="inputType === 'selector'"
class="px-4 py-6 rounded shadow-md"
:class="isNestedVariant ? 'bg-denim-800' : 'bg-denim-600'"
>
<FormConditions v-model="arg" />
</div>
<FormOperations v-if="inputType === 'selector'" v-model="arg" />
<InputAttributeOperator
v-if="inputType === 'attributeOperator'"
:label="label"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<InputPipe
class="w-full"
:modelValue="pipeOption"
@update:modelValue="option => condition = ({ ...condition, args: toDefaultValues(option.value), pipe: option.value })"
@update:modelValue="option => operation = ({ ...operation, args: toDefaultValues(option.value), pipe: option.value })"
/>
</div>
<button
Expand Down Expand Up @@ -42,8 +42,8 @@
:label="arg.label"
:inputType="arg.inputType"
:required="arg.required"
:modelValue="condition.args[index]"
@update:modelValue="arg => condition = ({ ...condition, args: createReplace({ index, item: arg })(condition.args) })"
:modelValue="operation.args[index]"
@update:modelValue="arg => operation = ({ ...operation, args: createReplace({ index, item: arg })(operation.args) })"
/>
<!-- Arg repetition should be handled here -->
</section>
Expand All @@ -57,7 +57,7 @@ import {
ChevronUpIcon,
ChevronDownIcon,
} from '@heroicons/vue/outline'
import type { Condition } from '../toSelector'
import type { Operation } from '../toSelector'
import InputPipe from './InputPipe.vue'
import FormArg from './FormArg.vue'
import { pipeMetadata } from '../pipeMetadata'
Expand All @@ -72,19 +72,19 @@ export default defineComponent({
},
props: ['modelValue', 'label'],
setup (props, { emit }) {
const condition = computed<Condition>({
const operation = computed<Operation>({
get: () => props.modelValue,
set: value => {
emit('update:modelValue', value)
}
}),
pipe = computed(() => pipeMetadata.find(({ label }) => label === condition.value.pipe)),
pipe = computed(() => pipeMetadata.find(({ label }) => label === operation.value.pipe)),
pipeOption = computed(() => ({
value: pipe.value.name,
label: pipe.value.label,
})),
emitDelete = () => {
emit('delete', condition.value.id)
emit('delete', operation.value.id)
},
emitMoveUp = () => {
emit('moveUp')
Expand All @@ -94,7 +94,7 @@ export default defineComponent({
}
return {
condition,
operation,
pipe,
pipeOption,
createReplace,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<template>
<section class="flex flex-col gap-10" :class="isNestedVariant ? 'text-denim-100' : 'text-denim-200'">
<section
class="flex flex-col gap-10 rounded-md shadow-lg"
:class="[
isNestedVariant ? 'bg-denim-600 text-denim-100' : 'bg-denim-800 text-denim-200',
nestingLevel === 0 ? 'px-6 py-8' : 'px-4 py-6'
]"
>
<h2
class="text-3xl font-mono uppercase tracking-[.2em] text-center"
:class="isNestedVariant ? '' : ''"
Expand All @@ -16,8 +22,8 @@
moveClass="transition duration-100"
>
<div
v-for="(condition, index) in conditions"
:key="condition.id"
v-for="(operation, index) in operations"
:key="operation.id"
class="flex flex-col gap-6"
>
<div class="flex items-center justify-center gap-3 font-mono">
Expand All @@ -44,23 +50,32 @@
:class="isNestedVariant ? 'bg-denim-400' : 'bg-denim-600'"
/>
</div>
<FormCondition
:modelValue="condition"
@update:modelValue="conditionUpdate"
@delete="conditionDelete"
@moveUp="() => { if (index !== 0) conditionReorder(condition.id, index - 1) }"
@moveDown="() => { if (index !== conditions.length - 1) conditionReorder(condition.id, index + 1) }"
<FormOperation
:modelValue="operation"
@update:modelValue="operationUpdate"
@delete="operationDelete"
@moveUp="() => { if (index !== 0) operationReorder(operation.id, index - 1) }"
@moveDown="() => { if (index !== operations.length - 1) operationReorder(operation.id, index + 1) }"
/>
</div>
</transition-group>
<button
name="Add condition"
class="mx-auto p-3 text-2xl btn--raised btn--grows rounded-full p-3 brand-gradient-to-r flex-shrink-0"
@click="conditionCreate"
@click="operationCreate"
type="button"
>
<PlusIcon class="h-[1em] w-[1em]"></PlusIcon>
</button>
</section>
<button
name="Add conditions"
class="mx-auto p-3 text-2xl btn--raised btn--grows rounded-full p-3 brand-gradient-to-r flex-shrink-0"
@click="operationCreate"
type="button"
>
<PlusIcon class="h-[1em] w-[1em]"></PlusIcon>
</button>
</template>

<script lang="ts">
Expand All @@ -69,59 +84,59 @@ import type { Ref } from 'vue'
import { nanoid } from 'nanoid'
import { createReorder } from '@baleada/logic'
import { PlusIcon } from '@heroicons/vue/solid'
import type { Condition } from '../toSelector'
import FormCondition from './FormCondition.vue'
import type { Operation } from '../toSelector'
import FormOperation from './FormOperation.vue'
import { pipeMetadata } from '../pipeMetadata'
import { NESTING_LEVEL_SYMBOL, NESTED_STATUS_SYMBOL } from '../state'
export default defineComponent({
name: 'FormConditions',
name: 'FormOperations',
components: {
FormCondition,
FormOperation,
PlusIcon
},
props: ['modelValue', 'isTopLevel'],
setup (props, { emit }) {
const conditions = computed<Condition[]>({
const operations = computed<Operation[]>({
get: () => props.modelValue,
set: conditions => {
emit('update:modelValue', conditions)
set: operations => {
emit('update:modelValue', operations)
}
}),
conditionCreate = () => {
conditions.value = [
...conditions.value,
operationCreate = () => {
operations.value = [
...operations.value,
{
id: nanoid(8),
pipe: pipeMetadata[0].label,
args: []
}
]
},
conditionDelete = (id: string) => {
const conditionIndex = findConditionIndex({ id, conditions }),
before = conditionIndex === 0 ? [] : conditions.value.slice(0, conditionIndex),
after = conditions.value.slice(conditionIndex + 1)
operationDelete = (id: string) => {
const operationIndex = findOperationIndex({ id, operations }),
before = operationIndex === 0 ? [] : operations.value.slice(0, operationIndex),
after = operations.value.slice(operationIndex + 1)
conditions.value = [
operations.value = [
...before,
...after,
]
},
conditionUpdate = (condition: Condition) => {
const index = findConditionIndex({ id: condition.id, conditions }),
before = index === 0 ? [] : conditions.value.slice(0, index),
after = conditions.value.slice(index + 1)
operationUpdate = (operation: Operation) => {
const index = findOperationIndex({ id: operation.id, operations }),
before = index === 0 ? [] : operations.value.slice(0, index),
after = operations.value.slice(index + 1)
conditions.value = [
operations.value = [
...before,
condition,
operation,
...after,
]
},
conditionReorder = (id: string, to: number) => {
const index = findConditionIndex({ id, conditions })
conditions.value = createReorder<Condition>({ from: index, to })(conditions.value)
operationReorder = (id: string, to: number) => {
const index = findOperationIndex({ id, operations })
operations.value = createReorder<Operation>({ from: index, to })(operations.value)
},
nestingLevel = shallowRef(props.isTopLevel ? 0 : inject<number>(NESTING_LEVEL_SYMBOL) + 1),
isNestedVariant = shallowRef(nestingLevel.value % 2 !== 0)
Expand All @@ -130,18 +145,18 @@ export default defineComponent({
provide(NESTED_STATUS_SYMBOL, isNestedVariant.value)
return {
conditions,
conditionCreate,
conditionDelete,
conditionUpdate,
conditionReorder,
operations,
operationCreate,
operationDelete,
operationUpdate,
operationReorder,
nestingLevel,
isNestedVariant,
}
},
})
function findConditionIndex ({ id, conditions }: { id: string, conditions: Ref<Condition[]> }) {
return conditions.value.findIndex(({ id: i }) => i === id)
function findOperationIndex ({ id, operations }: { id: string, operations: Ref<Operation[]> }) {
return operations.value.findIndex(({ id: i }) => i === id)
}
</script>
4 changes: 2 additions & 2 deletions src/interface/components/PopoverHelp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
<h2 class="mr-auto font-bold text-2xl bg-gradient-to-r from-violet-600 to-violet-400 bg-clip-text text-transparent">What is this?</h2>
<p>This is a user interface for building CSS selectors and learning what types of CSS selectors are available.</p>

<p><strong class="bg-gradient-to-r from-violet-600 to-violet-400 bg-clip-text text-transparent">Click the plus button</strong> to start adding conditions for your selector.</p>
<p><strong class="bg-gradient-to-r from-violet-600 to-violet-400 bg-clip-text text-transparent">Click the plus button</strong> to start adding operations for your selector.</p>

<p>As you build, you'll see the URL update with any new conditions you've created. You can <strong class="bg-gradient-to-r from-violet-600 to-violet-400 bg-clip-text text-transparent">share that URL</strong> with anyone to show them what you've built!</p>
<p>As you build, you'll see the URL update with any new operations you've created. You can <strong class="bg-gradient-to-r from-violet-600 to-violet-400 bg-clip-text text-transparent">share that URL</strong> with anyone to show them what you've built!</p>
</article>
</div>
</PopoverPanel>
Expand Down
4 changes: 2 additions & 2 deletions src/interface/entry.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { createApp } from 'vue'
import CssSelectorBuilder from './CssSelectorBuilder.vue'
import FormConditions from './components/FormConditions.vue'
import FormOperations from './components/FormOperations.vue'
import './index.css'
import '@fontsource/inconsolata/400.css'
import '@fontsource/inter/400.css'
import '@fontsource/inter/700.css'

createApp(CssSelectorBuilder)
.component('FormConditions', FormConditions)
.component('FormOperations', FormOperations)
.mount('#app')
4 changes: 2 additions & 2 deletions src/interface/pipeMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as pipes from '../pipes'
import type { AttributeOperator } from '../pipes'
import type { Condition } from './toSelector'
import type { Operation } from './toSelector'
import {
attributeCaseSensitivityDefault,
attributeOperatorDefault,
Expand All @@ -16,7 +16,7 @@ type PipeMetadatum = {
name: string,
inputType: 'unknown' | 'string' | 'selector' | 'attributeOperator' | 'attributeCaseSensitivity' | 'directionality' | 'nthPattern',
label: string,
defaultValue: string | boolean | number | Condition[],
defaultValue: string | boolean | number | Operation[],
required: boolean,
repeatable?: boolean,
}[]
Expand Down
6 changes: 3 additions & 3 deletions src/interface/toSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import type { Pipe } from '../pipes'
import { pipe } from '../pipes/util'
import { pipeMetadata } from './pipeMetadata'

export type Condition = {
export type Operation = {
id: string,
pipe: string,
args: any[],
}

export function toSelector (conditions: Condition[] = []) {
const reduced: Pipe[] = conditions.reduce((reduced, { pipe, args: rawArgs }) => {
export function toSelector (operations: Operation[] = []) {
const reduced: Pipe[] = operations.reduce((reduced, { pipe, args: rawArgs }) => {
const pipeName = pipeMetadata.find(({ label }) => label === pipe).name
const args = rawArgs.map(arg => Array.isArray(arg) ? toSelector(arg) : arg)

Expand Down
Loading

0 comments on commit 53535f6

Please sign in to comment.