Skip to content

Commit 8c7315b

Browse files
feat(client): use browser native UI on date editing (#275)
1 parent 15572f9 commit 8c7315b

File tree

8 files changed

+36
-8
lines changed

8 files changed

+36
-8
lines changed

packages/client/src/components/inspector/InspectorDataField/EditInput.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ const emit = defineEmits<{
1919
'update:modelValue': [value: string]
2020
}>()
2121
22+
const inputType = computed(() => {
23+
if (props.customType === 'date')
24+
return 'datetime-local'
25+
return ''
26+
})
27+
2228
// TODO: keyboard shortcut, esc to cancel, enter to submit
2329
// and show tooltip on button when hovering
2430
@@ -52,7 +58,7 @@ watch(value, checkWarning())
5258

5359
<template>
5460
<span class="flex-inline items-center gap4px">
55-
<VueInput v-model="value" :variant="isWarning ? 'warning' : 'normal'" class="h25px w120px px4px" :auto-focus="autoFocus" @click.stop />
61+
<VueInput v-model="value" :type="inputType" :variant="isWarning ? 'warning' : 'normal'" class="h25px px4px" :class="customType === 'date' ? 'w240px' : 'w120px'" :auto-focus="autoFocus" @click.stop />
5662
<template v-if="showActions">
5763
<VueButton
5864
v-tooltip="{

packages/devtools-kit/__tests__/component/format.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ describe('format: toEdit', () => {
9090
{ value: { foo: NEGATIVE_INFINITY }, target: '{"foo":-Infinity}' },
9191
{ value: { foo: UNDEFINED }, target: '{"foo":undefined}' },
9292
{ value: '123', customType: 'bigint' as customTypeEnums, target: '123' },
93+
{ value: '2024-03-12T00:00:55.666', customType: 'date' as customTypeEnums, target: '2024-03-12T00:00:55.666' },
9394
])('value: $value will be deserialized to target', (value) => {
9495
const deserialized = format.toEdit(value.value, value.customType)
9596
expect(deserialized).toBe(value.target)
@@ -117,6 +118,7 @@ describe('format: toSubmit', () => {
117118
// Regex test: The token in key field kept untouched.
118119
{ value: '{"undefined": NaN }', target: { undefined: Number.NaN } },
119120
{ value: '123', customType: 'bigint' as customTypeEnums, target: BigInt(123) },
121+
{ value: '2024-03-12T00:00:55.666', customType: 'date' as customTypeEnums, target: new Date('2024-03-12T00:00:55.666') },
120122
])('value: $value will be serialized to target', (value) => {
121123
const serialized = format.toSubmit(value.value, value.customType)
122124
expect(serialized).toStrictEqual(value.target)

packages/devtools-kit/src/core/component/state/custom.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ export function getBigIntDetails(val: bigint | bigint) {
3939
}
4040
}
4141

42+
export function getDateDetails(val: Date) {
43+
const date = new Date(val.getTime())
44+
date.setMinutes(date.getMinutes() - date.getTimezoneOffset())
45+
46+
return {
47+
_custom: {
48+
type: 'date',
49+
displayText: Date.prototype.toString.call(val),
50+
value: date.toISOString().slice(0, -1),
51+
},
52+
}
53+
}
54+
4255
export function getMapDetails(val: Map<string, unknown>) {
4356
const list: Record<string, unknown> = Object.fromEntries(val)
4457
return {

packages/devtools-kit/src/core/component/state/format.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,17 @@ export function getRaw(value: InspectorState['value']): {
118118
export function toEdit(value: unknown, customType?: customTypeEnums) {
119119
if (customType === 'bigint')
120120
return value as string
121+
if (customType === 'date')
122+
return value as string
121123

122124
return replaceTokenToString(JSON.stringify(value))
123125
}
124126

125127
export function toSubmit(value: string, customType?: customTypeEnums) {
126128
if (customType === 'bigint')
127129
return BigInt(value)
130+
if (customType === 'date')
131+
return new Date(value)
128132

129133
return JSON.parse(replaceStringToToken(value), reviver)
130134
}

packages/devtools-kit/src/core/component/state/replacer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { INFINITY, MAX_ARRAY_SIZE, MAX_STRING_SIZE, NAN, NEGATIVE_INFINITY, UNDEFINED } from './constants'
2-
import { getBigIntDetails, getComponentDefinitionDetails, getFunctionDetails, getHTMLElementDetails, getInstanceDetails, getMapDetails, getObjectDetails, getRouterDetails, getSetDetails, getStoreDetails } from './custom'
2+
import { getBigIntDetails, getComponentDefinitionDetails, getDateDetails, getFunctionDetails, getHTMLElementDetails, getInstanceDetails, getMapDetails, getObjectDetails, getRouterDetails, getSetDetails, getStoreDetails } from './custom'
33
import { isVueInstance } from './is'
44
import { sanitize } from './util'
55

@@ -62,7 +62,7 @@ export function stringifyReplacer(key: string) {
6262
return `[native RegExp ${RegExp.prototype.toString.call(val)}]`
6363
}
6464
else if (proto === '[object Date]') {
65-
return `[native Date ${Date.prototype.toString.call(val)}]`
65+
return getDateDetails(val as Date)
6666
}
6767
else if (proto === '[object Error]') {
6868
return `[native Error ${(val as Error).message}<>${(val as Error).stack}]`
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export type customTypeEnums = 'function' | 'bigint' | 'map' | 'set' | 'store' | 'router' | 'component' | 'component-definition' | 'HTMLElement' | 'component-definition'
1+
export type customTypeEnums = 'function' | 'bigint' | 'map' | 'set' | 'store' | 'router' | 'component' | 'component-definition' | 'HTMLElement' | 'component-definition' | 'date'

packages/ui/src/components/Input.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ const props = withDefaults(defineProps<{
99
placeholder?: string
1010
variant?: 'normal' | 'accent' | 'flat' | 'warning'
1111
disabled?: boolean
12-
password?: boolean
1312
leftIcon?: string
1413
rightIcon?: string
1514
loading?: boolean
1615
autoFocus?: boolean
1716
loadingDebounceTime?: number
1817
readonly?: boolean
18+
type?: string
1919
}>(), {
2020
placeholder: '',
2121
variant: 'normal',
2222
disabled: false,
23-
password: false,
23+
type: 'text',
2424
/**
2525
* loading will auto enable disabled
2626
*/
@@ -101,7 +101,7 @@ watchEffect(() => {
101101
</div>
102102
<input
103103
ref="inputRef" v-model="value"
104-
class="$ui-base w-full bg-transparent color-inherit outline-none placeholder-color-gray-500 dark:placeholder-gray-300" :type="props.password ? 'password' : 'text'"
104+
class="$ui-base w-full bg-transparent color-inherit outline-none placeholder-color-gray-500 dark:placeholder-gray-300" :type="type"
105105
:placeholder="placeholder" :disabled="disabled || readonly"
106106
@blur="focused = false"
107107
>

packages/ui/storybook/Input.story.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ watchEffect(() => {
4444
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" variant="flat" />
4545
</Variant>
4646
<Variant title="password">
47-
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" password />
47+
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" type="password" />
48+
</Variant>
49+
<Variant title="datetime-local">
50+
<Input v-model="value" :loading="loading" :disabled="disable" placeholder="Flat Input" type="datetime-local" />
4851
</Variant>
4952
<Variant title="icon">
5053
<Input

0 commit comments

Comments
 (0)