Skip to content

Commit

Permalink
feat(client): use browser native UI on date editing (#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
Azurewarth0920 authored Mar 12, 2024
1 parent 15572f9 commit 8c7315b
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ const emit = defineEmits<{
'update:modelValue': [value: string]
}>()
const inputType = computed(() => {
if (props.customType === 'date')
return 'datetime-local'
return ''
})
// TODO: keyboard shortcut, esc to cancel, enter to submit
// and show tooltip on button when hovering
Expand Down Expand Up @@ -52,7 +58,7 @@ watch(value, checkWarning())

<template>
<span class="flex-inline items-center gap4px">
<VueInput v-model="value" :variant="isWarning ? 'warning' : 'normal'" class="h25px w120px px4px" :auto-focus="autoFocus" @click.stop />
<VueInput v-model="value" :type="inputType" :variant="isWarning ? 'warning' : 'normal'" class="h25px px4px" :class="customType === 'date' ? 'w240px' : 'w120px'" :auto-focus="autoFocus" @click.stop />
<template v-if="showActions">
<VueButton
v-tooltip="{
Expand Down
2 changes: 2 additions & 0 deletions packages/devtools-kit/__tests__/component/format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ describe('format: toEdit', () => {
{ value: { foo: NEGATIVE_INFINITY }, target: '{"foo":-Infinity}' },
{ value: { foo: UNDEFINED }, target: '{"foo":undefined}' },
{ value: '123', customType: 'bigint' as customTypeEnums, target: '123' },
{ value: '2024-03-12T00:00:55.666', customType: 'date' as customTypeEnums, target: '2024-03-12T00:00:55.666' },
])('value: $value will be deserialized to target', (value) => {
const deserialized = format.toEdit(value.value, value.customType)
expect(deserialized).toBe(value.target)
Expand Down Expand Up @@ -117,6 +118,7 @@ describe('format: toSubmit', () => {
// Regex test: The token in key field kept untouched.
{ value: '{"undefined": NaN }', target: { undefined: Number.NaN } },
{ value: '123', customType: 'bigint' as customTypeEnums, target: BigInt(123) },
{ value: '2024-03-12T00:00:55.666', customType: 'date' as customTypeEnums, target: new Date('2024-03-12T00:00:55.666') },
])('value: $value will be serialized to target', (value) => {
const serialized = format.toSubmit(value.value, value.customType)
expect(serialized).toStrictEqual(value.target)
Expand Down
13 changes: 13 additions & 0 deletions packages/devtools-kit/src/core/component/state/custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ export function getBigIntDetails(val: bigint | bigint) {
}
}

export function getDateDetails(val: Date) {
const date = new Date(val.getTime())
date.setMinutes(date.getMinutes() - date.getTimezoneOffset())

return {
_custom: {
type: 'date',
displayText: Date.prototype.toString.call(val),
value: date.toISOString().slice(0, -1),
},
}
}

export function getMapDetails(val: Map<string, unknown>) {
const list: Record<string, unknown> = Object.fromEntries(val)
return {
Expand Down
4 changes: 4 additions & 0 deletions packages/devtools-kit/src/core/component/state/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,17 @@ export function getRaw(value: InspectorState['value']): {
export function toEdit(value: unknown, customType?: customTypeEnums) {
if (customType === 'bigint')
return value as string
if (customType === 'date')
return value as string

return replaceTokenToString(JSON.stringify(value))
}

export function toSubmit(value: string, customType?: customTypeEnums) {
if (customType === 'bigint')
return BigInt(value)
if (customType === 'date')
return new Date(value)

return JSON.parse(replaceStringToToken(value), reviver)
}
4 changes: 2 additions & 2 deletions packages/devtools-kit/src/core/component/state/replacer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { INFINITY, MAX_ARRAY_SIZE, MAX_STRING_SIZE, NAN, NEGATIVE_INFINITY, UNDEFINED } from './constants'
import { getBigIntDetails, getComponentDefinitionDetails, getFunctionDetails, getHTMLElementDetails, getInstanceDetails, getMapDetails, getObjectDetails, getRouterDetails, getSetDetails, getStoreDetails } from './custom'
import { getBigIntDetails, getComponentDefinitionDetails, getDateDetails, getFunctionDetails, getHTMLElementDetails, getInstanceDetails, getMapDetails, getObjectDetails, getRouterDetails, getSetDetails, getStoreDetails } from './custom'
import { isVueInstance } from './is'
import { sanitize } from './util'

Expand Down Expand Up @@ -62,7 +62,7 @@ export function stringifyReplacer(key: string) {
return `[native RegExp ${RegExp.prototype.toString.call(val)}]`
}
else if (proto === '[object Date]') {
return `[native Date ${Date.prototype.toString.call(val)}]`
return getDateDetails(val as Date)
}
else if (proto === '[object Error]') {
return `[native Error ${(val as Error).message}<>${(val as Error).stack}]`
Expand Down
2 changes: 1 addition & 1 deletion packages/devtools-kit/src/core/component/types/custom.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export type customTypeEnums = 'function' | 'bigint' | 'map' | 'set' | 'store' | 'router' | 'component' | 'component-definition' | 'HTMLElement' | 'component-definition'
export type customTypeEnums = 'function' | 'bigint' | 'map' | 'set' | 'store' | 'router' | 'component' | 'component-definition' | 'HTMLElement' | 'component-definition' | 'date'
6 changes: 3 additions & 3 deletions packages/ui/src/components/Input.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ const props = withDefaults(defineProps<{
placeholder?: string
variant?: 'normal' | 'accent' | 'flat' | 'warning'
disabled?: boolean
password?: boolean
leftIcon?: string
rightIcon?: string
loading?: boolean
autoFocus?: boolean
loadingDebounceTime?: number
readonly?: boolean
type?: string
}>(), {
placeholder: '',
variant: 'normal',
disabled: false,
password: false,
type: 'text',
/**
* loading will auto enable disabled
*/
Expand Down Expand Up @@ -101,7 +101,7 @@ watchEffect(() => {
</div>
<input
ref="inputRef" v-model="value"
class="$ui-base w-full bg-transparent color-inherit outline-none placeholder-color-gray-500 dark:placeholder-gray-300" :type="props.password ? 'password' : 'text'"
class="$ui-base w-full bg-transparent color-inherit outline-none placeholder-color-gray-500 dark:placeholder-gray-300" :type="type"
:placeholder="placeholder" :disabled="disabled || readonly"
@blur="focused = false"
>
Expand Down
5 changes: 4 additions & 1 deletion packages/ui/storybook/Input.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ watchEffect(() => {
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" variant="flat" />
</Variant>
<Variant title="password">
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" password />
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" type="password" />
</Variant>
<Variant title="datetime-local">
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" type="datetime-local" />
</Variant>
<Variant title="icon">
<Input
Expand Down

0 comments on commit 8c7315b

Please sign in to comment.