Skip to content

Commit

Permalink
wip: layout controls
Browse files Browse the repository at this point in the history
  • Loading branch information
arpowers committed Mar 5, 2024
1 parent eb3f605 commit 461169e
Show file tree
Hide file tree
Showing 15 changed files with 254 additions and 207 deletions.
21 changes: 10 additions & 11 deletions @fiction/core/plugin-db/test/utilUsername.ci.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { beforeAll, describe, expect, it } from 'vitest'
import { afterAll, describe, expect, it } from 'vitest'
import type { TestUtils } from '../../test-utils'
import { createTestUtils } from '../../test-utils'
import type { FictionDb } from '..'
import { objectId, shortId } from '../../utils'
import { standardTable } from '../../tbl'

let testUtils: TestUtils
let fictionDb: FictionDb
let userId: string | undefined
const table = standardTable.user
describe('check username', () => {
beforeAll(async () => {
testUtils = await createTestUtils()
fictionDb = testUtils.fictionDb
const initialized = await testUtils.init()
userId = initialized.user.userId
describe('check username', async () => {
const testUtils = await createTestUtils()
const fictionDb = testUtils.fictionDb
const initialized = await testUtils.init()
const userId = initialized.user.userId
const table = standardTable.user

afterAll(async () => {
await testUtils.close()
})

it('should return success for a valid, non-taken username', async () => {
Expand Down
9 changes: 5 additions & 4 deletions @fiction/core/utils/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export const colorList = {
0: '#ffffff',
25: '#fbfdff',
50: '#F8F9FD',
100: '#d7dce6',
100: '#e6e9f1',
200: '#c8cdd7',
300: '#949DAD',
300: '#b3b9c5',
400: '#7A8599',
500: '#646E82',
600: '#394151',
Expand Down Expand Up @@ -403,7 +403,7 @@ type ColorRecord = {
export type ColorScheme = keyof typeof colorList

export function hexToRgb(hex: string) {
const result = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(hex)
const result = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(hex.toLowerCase())
return result
? [
Number.parseInt(result[1], 16),
Expand All @@ -424,7 +424,8 @@ export function tailwindVarColorScheme(args: {
scheme = getColorScheme(color)

const entries = Object.entries(scheme || {}).map(([key, value]) => {
return [Number.parseInt(key), `rgb(var(--${variable}-${key}, ${hexToRgb(value)}) / <alpha-value>)`]
const defaultValue = value.includes('#') ? hexToRgb(value) : value
return [Number.parseInt(key), `rgb(var(--${variable}-${key}, ${defaultValue}) / <alpha-value>)`]
})

const out = Object.fromEntries(entries) as Record<ColorScale | 'DEFAULT', string>
Expand Down
34 changes: 18 additions & 16 deletions @fiction/core/utils/test/colors.ci.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,26 @@ describe('colors', () => {

expect(result).toMatchInlineSnapshot(`
{
"0": "rgb(var(--foo-0, undefined) / <alpha-value>)",
"100": "rgb(var(--foo-100, undefined) / <alpha-value>)",
"1000": "rgb(var(--foo-1000, undefined) / <alpha-value>)",
"200": "rgb(var(--foo-200, undefined) / <alpha-value>)",
"25": "rgb(var(--foo-25, undefined) / <alpha-value>)",
"300": "rgb(var(--foo-300, undefined) / <alpha-value>)",
"400": "rgb(var(--foo-400, undefined) / <alpha-value>)",
"50": "rgb(var(--foo-50, undefined) / <alpha-value>)",
"500": "rgb(var(--foo-500, undefined) / <alpha-value>)",
"600": "rgb(var(--foo-600, undefined) / <alpha-value>)",
"700": "rgb(var(--foo-700, undefined) / <alpha-value>)",
"800": "rgb(var(--foo-800, undefined) / <alpha-value>)",
"900": "rgb(var(--foo-900, undefined) / <alpha-value>)",
"950": "rgb(var(--foo-950, undefined) / <alpha-value>)",
"975": "rgb(var(--foo-975, undefined) / <alpha-value>)",
"DEFAULT": "rgb(var(--foo-500, undefined) / <alpha-value>)",
"0": "rgb(var(--foo-0, 255 255 255) / <alpha-value>)",
"100": "rgb(var(--foo-100, 241 245 249) / <alpha-value>)",
"1000": "rgb(var(--foo-1000, 0 0 0) / <alpha-value>)",
"200": "rgb(var(--foo-200, 226 232 240) / <alpha-value>)",
"25": "rgb(var(--foo-25, 250 251 252) / <alpha-value>)",
"300": "rgb(var(--foo-300, 203 213 225) / <alpha-value>)",
"400": "rgb(var(--foo-400, 148 163 184) / <alpha-value>)",
"50": "rgb(var(--foo-50, 248 250 252) / <alpha-value>)",
"500": "rgb(var(--foo-500, 100 116 139) / <alpha-value>)",
"600": "rgb(var(--foo-600, 71 85 105) / <alpha-value>)",
"700": "rgb(var(--foo-700, 51 65 85) / <alpha-value>)",
"800": "rgb(var(--foo-800, 30 41 59) / <alpha-value>)",
"900": "rgb(var(--foo-900, 15 23 42) / <alpha-value>)",
"950": "rgb(var(--foo-950, 9 14 27) / <alpha-value>)",
"975": "rgb(var(--foo-975, 2 6 23) / <alpha-value>)",
"DEFAULT": "rgb(var(--foo-500, 100 116 139) / <alpha-value>)",
}
`)

expect(result[0]).not.toContain('undefined')
})

it('generates correct CSS variables for Tailwind', () => {
Expand Down
10 changes: 4 additions & 6 deletions @fiction/plugin-sites/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,15 @@ export type EditorState = {
savedCardOrder: Record<string, string[]>
}

// interface CardRender<T extends ComponentConstructor = ComponentConstructor> {
// el?: vue.Component
// props?: Partial<InstanceType<T>['$props']>
// options: InputOption[]
// }
type CardCategory = 'basic' | 'stats' | 'marketing' | 'content' | 'layout' | 'media' | 'navigation' | 'social' | 'commerce' | 'form' | 'other' | 'special'

export const categoryOrder: CardCategory[] = ['basic', 'marketing', 'content', 'stats', 'layout', 'media', 'navigation', 'social', 'commerce', 'form', 'other', 'special']

interface CardTemplateSettings<U extends string = string, T extends ComponentConstructor = ComponentConstructor> {
templateId: U
title?: string
description?: string
category?: string[]
category?: CardCategory[]
icon?: string
iconTheme?: keyof typeof iconStyle
thumb?: string
Expand Down
10 changes: 7 additions & 3 deletions @fiction/plugin-sites/el/ElTool.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const ico = iconStyle[props.iconTheme]
<h3 class="font-semibold flex space-x-2 items-center">
<div
class="rounded-md p-1 size-7 border flex items-center justify-center"
:data-theme="iconTheme"
:class="[
ico.color, ico.bg, ico.border,
]"
Expand All @@ -43,14 +44,17 @@ const ico = iconStyle[props.iconTheme]
<div v-html="title || tool.title || toLabel(tool.toolId)" />
</h3>
</div>
<div class="">
<div class="flex space-x-2 text-xs items-center font-semibold text-theme-200">
<div
v-for="(item, i) in actions"
:key="i"
class="transition-all cursor-pointer text-theme-600 dark:text-theme-0 hover:bg-primary-100 dark:hover:bg-primary-700 hover:text-primary-500 rounded-md bg-theme-50 dark:bg-primary-800 p-1 text-xl border border-theme-300 dark:border-primary-500 hover:border-primary-300 "
class="flex space-x-1 items-center transition-all cursor-pointer text-theme-500 dark:text-theme-0 hover:bg-primary-100 dark:hover:bg-primary-700 hover:text-primary-500 rounded-md bg-theme-50 dark:bg-primary-800 py-1 px-2 text-[10px] border border-theme-200 dark:border-primary-500 hover:border-primary-300 "
@click="item.onClick?.({ event: $event, item })"
>
<div :class="item.icon" />
<div :class="item.icon" class="text-base" />
<div class="">
{{ item.name }}
</div>
</div>
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions @fiction/plugin-sites/el/ElToolHandle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const i = vue.computed(() => {
>
<div
class="handlebar flex group rounded-md select-none min-w-0 hover:opacity-80"
:class="[handle.isActive ? 'bg-primary-100 dark:bg-primary-900 text-primary-900 dark:text-primary-0' : '']"
:class="[handle.isActive ? 'bg-primary-50 dark:bg-primary-900 text-primary-700 dark:text-primary-0' : '']"
@mouseover="draggableMode = handle.depth"
@mouseleave="draggableMode = -1"
>
Expand All @@ -44,7 +44,7 @@ const i = vue.computed(() => {
class="flex grow border-y border-r min-w-0"
:class="[
handle.hasDrawer ? 'rounded-tr-md' : 'rounded-r-md',
handle.isActive ? 'dark:border-primary-500' : 'dark:border-theme-500']"
handle.isActive ? 'dark:border-primary-500 border-primary-300' : 'dark:border-theme-500 border-theme-200']"
>
<div
class="flex grow cursor-pointer items-center px-3 truncate gap-1 text-[10px] min-w-0"
Expand All @@ -53,7 +53,7 @@ const i = vue.computed(() => {
<div class="py-1 uppercase font-medium tracking-wide shrink-0">
{{ handle.title || "Untitled" }}
</div>
<div v-if="handle.sub" class="py-1 text-theme-400 font-medium italic truncate">
<div v-if="handle.sub" class="py-1 text-theme-400 font-medium italic truncate" :class="handle.isActive ? 'text-primary-300' : 'text-theme-400'">
{{ handle.sub }}
</div>
</div>
Expand Down
114 changes: 30 additions & 84 deletions @fiction/plugin-sites/el/LayoutTool.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
<script lang="ts" setup>
import type { ActionItem, ListItem } from '@fiction/core'
import { toLabel, vue } from '@fiction/core'
import { vue } from '@fiction/core'
import ElInput from '@fiction/ui/ElInput.vue'
import ElButton from '@fiction/ui/ElButton.vue'
import type { Site } from '../site'
import type { Card } from '../card'
import type { EditorTool, Handle } from './tools'
import type { EditorTool } from './tools'
import ElTool from './ElTool.vue'
import ElToolHandle from './ElToolHandle.vue'
import TransitionList from './TransitionList.vue'
import DraggableLayout from './LayoutDraggable.vue'
import LayoutToolRegion from './LayoutToolRegion.vue'
const props = defineProps({
site: {
Expand All @@ -22,36 +21,6 @@ const props = defineProps({
})
const control = props.site.settings.fictionSites
function getCardHandle(card: Card): Handle {
return {
title: card.tpl.value?.settings.title ?? 'Card',
sub: card.title.value,
handleId: card.cardId,
icon: card.tpl.value?.settings.icon,
iconTheme: card.tpl.value?.settings.iconTheme,
depth: card.depth.value,
isDraggable: true,
hasDrawer: card.tpl.value?.settings.isContainer ?? false,
handles: card.cards.value.map(c => getCardHandle(c)),
isActive: card.cardId === props.site.editor.value.selectedCardId,
actions: [
{
name: 'Edit',
icon: 'i-tabler-edit',
onClick: () => {
props.site.setActiveCard({ cardId: card.cardId })
},
},
{
name: 'Delete',
icon: 'i-tabler-trash',
onClick: () => {
props.site.removeCard({ cardId: card.cardId })
},
},
],
}
}
const actions: ActionItem[] = [
{
Expand All @@ -77,58 +46,35 @@ const pageList = vue.computed<ListItem[]>(() => {
<template>
<ElTool :tool="tool" :actions="actions">
<div class="list relative p-4">
<ElInput
v-model="site.activePageId.value"
label="Selected Page"
input="InputSelectCustom"
:list="pageList"
class="mb-8"
/>

<DraggableLayout class="relative rounded-md" @update:model-value="site.updateLayout({ order: $event })">
<div
v-for="(card, regionId) in site.layout.value"
:key="regionId"
class="pb-4"
:data-region-id="card.cardId"
>
<div class="relative my-1">
<div
class="absolute inset-0 flex items-center"
aria-hidden="true"
>
<div class="w-full border-t border-theme-200 dark:border-theme-600" />
</div>
<div class="relative flex justify-start">
<span
class="bg-white dark:bg-theme-900 pr-2 text-[10px] uppercase text-theme-300"
>{{ toLabel(regionId) }}</span>
</div>
<DraggableLayout class="relative rounded-md space-y-4" @update:model-value="site.updateLayout({ order: $event })">
<div class=" rounded-md space-y-1">
<div class="relative flex justify-between items-center">
<span class="text-[10px] uppercase text-theme-400/40 font-semibold tracking-wide">Current Page</span>
<ElButton size="xxs" @click="control.useTool({ toolId: 'pages' })">
Change Page
</ElButton>
</div>

<LayoutToolRegion region-id="main" :card="site.currentPage.value" :site="site" />
<ElInput
v-model="site.activePageId.value"
class="hidden"
label="Active Page"
input="InputSelectCustom"
:list="pageList"
/>
</div>
<div class="rounded-md space-y-1">
<div class="relative">
<div
v-if="!card.cards.value.length"
key="add"
class="hidden border-3 border-dashed border-theme-200 rounded-lg mt-2 p-4 text-xs text-center hover:border-theme-300 cursor-pointer text-theme-300 hover:text-theme-400 font-semibold"
@click="site.activeRegionKey.value = regionId; control.useTool({ toolId: 'add' })"
>
Add Element
</div>
<TransitionList
tag="div"
class="space-y-2 sortable-zone min-h-[30px] rounded-md"
data-drag-zone
data-drag-depth="1"
:disabled="site.isAnimationDisabled.value"
>
<ElToolHandle
v-for="cardObj in card.cards.value"
:key="cardObj.cardId"
:handle="getCardHandle(cardObj)"
/>
</TransitionList>
<span class="text-[10px] uppercase text-theme-400/40 font-semibold tracking-wide">Global Areas</span>
</div>

<LayoutToolRegion
v-for="(card, regionId) in site.sections.value"
:key="regionId"
:region-id="regionId"
:card="card"
:site="site"
/>
</div>
</DraggableLayout>
</div>
Expand Down
Loading

0 comments on commit 461169e

Please sign in to comment.