add MkGrid.stories.impl.ts
This commit is contained in:
parent
5a2b11ec17
commit
098cf397b9
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* AIで生成した無作為なファーストネーム
|
||||||
|
*/
|
||||||
|
export const firstNameDict: string = [
|
||||||
|
'Ethan', 'Olivia', 'Jackson', 'Emma', 'Liam', 'Ava', 'Aiden', 'Sophia', 'Mason', 'Isabella',
|
||||||
|
'Noah', 'Mia', 'Lucas', 'Harper', 'Caleb', 'Abigail', 'Samuel', 'Emily', 'Logan',
|
||||||
|
'Madison', 'Benjamin', 'Chloe', 'Elijah', 'Grace', 'Alexander', 'Scarlett', 'William', 'Zoey', 'James', 'Lily',
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AIで生成した無作為なラストネーム
|
||||||
|
*/
|
||||||
|
export const lastNameDict: string = [
|
||||||
|
'Anderson', 'Johnson', 'Thompson', 'Davis', 'Rodriguez', 'Smith', 'Patel', 'Williams', 'Lee', 'Brown',
|
||||||
|
'Garcia', 'Jackson', 'Martinez', 'Taylor', 'Harris', 'Nguyen', 'Miller', 'Jones', 'Wilson',
|
||||||
|
'White', 'Thomas', 'Garcia', 'Martinez', 'Robinson', 'Turner', 'Lewis', 'Hall', 'King', 'Baker', 'Cooper',
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AIで生成した無作為な国名
|
||||||
|
*/
|
||||||
|
export const countryDict: string = [
|
||||||
|
'Japan', 'Canada', 'Brazil', 'Australia', 'Italy', 'SouthAfrica', 'Mexico', 'Sweden', 'Russia', 'India',
|
||||||
|
'Germany', 'Argentina', 'South Korea', 'France', 'Nigeria', 'Turkey', 'Spain', 'Egypt', 'Thailand',
|
||||||
|
'Vietnam', 'Kenya', 'Saudi Arabia', 'Netherlands', 'Colombia', 'Poland', 'Chile', 'Malaysia', 'Ukraine', 'New Zealand', 'Peru',
|
||||||
|
]
|
||||||
|
|
||||||
|
export function text(length: number = 10): string {
|
||||||
|
let result = "";
|
||||||
|
|
||||||
|
while (result.length < length) {
|
||||||
|
result += Math.random().toString(36).substring(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.substring(0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integer(min: number = 0, max: number = 9999): number {
|
||||||
|
return Math.floor(Math.random() * (max - min)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function date(params?: {
|
||||||
|
yearMin?: number,
|
||||||
|
yearMax?: number,
|
||||||
|
monthMin?: number,
|
||||||
|
monthMax?: number,
|
||||||
|
dayMin?: number,
|
||||||
|
dayMax?: number,
|
||||||
|
hourMin?: number,
|
||||||
|
hourMax?: number,
|
||||||
|
minuteMin?: number,
|
||||||
|
minuteMax?: number,
|
||||||
|
secondMin?: number,
|
||||||
|
secondMax?: number,
|
||||||
|
millisecondMin?: number,
|
||||||
|
millisecondMax?: number,
|
||||||
|
}) {
|
||||||
|
const year = integer(params?.yearMin ?? 1970, params?.yearMax ?? (new Date()).getFullYear());
|
||||||
|
const month = integer(params?.monthMin ?? 1, params?.monthMax ?? 12);
|
||||||
|
let day = integer(params?.dayMin ?? 1, params?.dayMax ?? 31);
|
||||||
|
if (month === 2) {
|
||||||
|
day = Math.min(day, 28);
|
||||||
|
} else if ([4, 6, 9, 11].includes(month)) {
|
||||||
|
day = Math.min(day, 30);
|
||||||
|
} else {
|
||||||
|
day = Math.min(day, 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hour = integer(params?.hourMin ?? 0, params?.hourMax ?? 23);
|
||||||
|
const minute = integer(params?.minuteMin ?? 0, params?.minuteMax ?? 59);
|
||||||
|
const second = integer(params?.secondMin ?? 0, params?.secondMax ?? 59);
|
||||||
|
const millisecond = integer(params?.millisecondMin ?? 0, params?.millisecondMax ?? 999);
|
||||||
|
|
||||||
|
return new Date(year, month - 1, day, hour, minute, second, millisecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function boolean(): boolean {
|
||||||
|
return Math.random() < 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function choose<T>(array: T[]): T {
|
||||||
|
return array[Math.floor(Math.random() * array.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function firstName(): string {
|
||||||
|
return firstNameDict[Math.floor(Math.random() * firstNameDict.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lastName(): string {
|
||||||
|
return lastNameDict[Math.floor(Math.random() * lastNameDict.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function country(): string {
|
||||||
|
return countryDict[Math.floor(Math.random() * countryDict.length)];
|
||||||
|
}
|
|
@ -411,6 +411,7 @@ function toStories(component: string): Promise<string> {
|
||||||
glob('src/components/MkInviteCode.vue'),
|
glob('src/components/MkInviteCode.vue'),
|
||||||
glob('src/components/MkTagItem.vue'),
|
glob('src/components/MkTagItem.vue'),
|
||||||
glob('src/components/MkRoleSelectDialog.vue'),
|
glob('src/components/MkRoleSelectDialog.vue'),
|
||||||
|
glob('src/components/grid/MkGrid.vue'),
|
||||||
glob('src/pages/user/home.vue'),
|
glob('src/pages/user/home.vue'),
|
||||||
]);
|
]);
|
||||||
const components = globs.flat();
|
const components = globs.flat();
|
||||||
|
|
|
@ -22,6 +22,12 @@
|
||||||
<div v-if="cellType === 'text'">
|
<div v-if="cellType === 'text'">
|
||||||
{{ cell.value }}
|
{{ cell.value }}
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="cellType === 'number'">
|
||||||
|
{{ cell.value }}
|
||||||
|
</div>
|
||||||
|
<div v-if="cellType === 'date'">
|
||||||
|
{{ cell.value }}
|
||||||
|
</div>
|
||||||
<div v-else-if="cellType === 'boolean'">
|
<div v-else-if="cellType === 'boolean'">
|
||||||
<span v-if="cell.value === true" class="ti ti-check"/>
|
<span v-if="cell.value === true" class="ti ti-check"/>
|
||||||
<span v-else class="ti"/>
|
<span v-else class="ti"/>
|
||||||
|
@ -46,6 +52,24 @@
|
||||||
@mousedown.stop
|
@mousedown.stop
|
||||||
@contextmenu.stop
|
@contextmenu.stop
|
||||||
/>
|
/>
|
||||||
|
<input
|
||||||
|
v-if="cellType === 'number'"
|
||||||
|
type="number"
|
||||||
|
:class="$style.editingInput"
|
||||||
|
:value="editingValue"
|
||||||
|
@input="onInputText"
|
||||||
|
@mousedown.stop
|
||||||
|
@contextmenu.stop
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-if="cellType === 'date'"
|
||||||
|
type="date"
|
||||||
|
:class="$style.editingInput"
|
||||||
|
:value="editingValue"
|
||||||
|
@input="onInputText"
|
||||||
|
@mousedown.stop
|
||||||
|
@contextmenu.stop
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
@ -185,6 +209,8 @@ async function beginEditing(target: HTMLElement) {
|
||||||
rootEl.value?.focus();
|
rootEl.value?.focus();
|
||||||
} else {
|
} else {
|
||||||
switch (cellType.value) {
|
switch (cellType.value) {
|
||||||
|
case 'number':
|
||||||
|
case 'date':
|
||||||
case 'text': {
|
case 'text': {
|
||||||
editingValue.value = cell.value.value;
|
editingValue.value = cell.value.value;
|
||||||
editing.value = true;
|
editing.value = true;
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import { StoryObj } from '@storybook/vue3';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { commonHandlers } from '../../../.storybook/mocks.js';
|
||||||
|
import { boolean, choose, country, date, firstName, integer, lastName, text } from '../../../.storybook/fake-utils.js';
|
||||||
|
import MkGrid from './MkGrid.vue';
|
||||||
|
import { GridContext, GridEvent } from '@/components/grid/grid-event.js';
|
||||||
|
import { DataSource, GridSetting } from '@/components/grid/grid.js';
|
||||||
|
|
||||||
|
function d(p: {
|
||||||
|
check?: boolean,
|
||||||
|
name?: string,
|
||||||
|
email?: string,
|
||||||
|
age?: number,
|
||||||
|
birthday?: string,
|
||||||
|
gender?: string,
|
||||||
|
country?: string,
|
||||||
|
reportCount?: number,
|
||||||
|
createdAt?: string,
|
||||||
|
}) {
|
||||||
|
const prefix = text(10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
check: p.check ?? boolean(),
|
||||||
|
name: p.name ?? `${firstName()} ${lastName()}`,
|
||||||
|
email: p.email ?? `${prefix}@example.com`,
|
||||||
|
age: p.age ?? integer(20, 80),
|
||||||
|
birthday: date().toISOString(),
|
||||||
|
gender: p.gender ?? choose(['male', 'female', 'other', 'unknown']),
|
||||||
|
country: p.country ?? country(),
|
||||||
|
reportCount: p.reportCount ?? integer(),
|
||||||
|
createdAt: p.createdAt ?? date().toISOString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultCols = [
|
||||||
|
{ bindTo: 'check', icon: 'ti-check', type: 'boolean', width: 50 },
|
||||||
|
{ bindTo: 'name', title: 'Name', type: 'text', width: 'auto' },
|
||||||
|
{ bindTo: 'email', title: 'Email', type: 'text', width: 'auto' },
|
||||||
|
{ bindTo: 'age', title: 'Age', type: 'number', width: 50 },
|
||||||
|
{ bindTo: 'birthday', title: 'Birthday', type: 'date', width: 'auto' },
|
||||||
|
{ bindTo: 'gender', title: 'Gender', type: 'text', width: 80 },
|
||||||
|
{ bindTo: 'country', title: 'Country', type: 'text', width: 120 },
|
||||||
|
{ bindTo: 'reportCount', title: 'ReportCount', type: 'number', width: 'auto' },
|
||||||
|
{ bindTo: 'createdAt', title: 'CreatedAt', type: 'date', width: 'auto' },
|
||||||
|
];
|
||||||
|
|
||||||
|
function createArgs(overrides?: { settings?: Partial<GridSetting>, data?: DataSource[] }) {
|
||||||
|
const refData = ref([
|
||||||
|
d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}),
|
||||||
|
d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}),
|
||||||
|
d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}),
|
||||||
|
d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}),
|
||||||
|
d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}), d({}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
settings: {
|
||||||
|
row: overrides?.settings?.row,
|
||||||
|
cols: [
|
||||||
|
...defaultCols.filter(col => overrides?.settings?.cols?.every(c => c.bindTo !== col.bindTo) ?? true),
|
||||||
|
...overrides?.settings?.cols ?? [],
|
||||||
|
],
|
||||||
|
cells: overrides?.settings?.cells,
|
||||||
|
},
|
||||||
|
data: refData.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRender(params: { settings: Partial<GridSetting>, data: DataSource[] }) {
|
||||||
|
return {
|
||||||
|
render(args) {
|
||||||
|
return {
|
||||||
|
components: {
|
||||||
|
MkGrid,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
data: args.data,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
props() {
|
||||||
|
return {
|
||||||
|
...args,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
events() {
|
||||||
|
return {
|
||||||
|
event: (event: GridEvent, context: GridContext) => {
|
||||||
|
switch (event.type) {
|
||||||
|
case 'cell-value-change': {
|
||||||
|
args.data[event.row.index][event.column.setting.bindTo] = event.newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
template: '<div style="padding:20px"><MkGrid v-bind="props" v-on="events" /></div>',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
layout: 'fullscreen',
|
||||||
|
msw: {
|
||||||
|
handlers: [
|
||||||
|
...commonHandlers,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies StoryObj<typeof MkGrid>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Default = createRender(createArgs());
|
||||||
|
|
||||||
|
export const NoNumber = createRender(createArgs({
|
||||||
|
settings: {
|
||||||
|
row: {
|
||||||
|
showNumber: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const NoSelectable = createRender(createArgs({
|
||||||
|
settings: {
|
||||||
|
row: {
|
||||||
|
selectable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const Editable = createRender(createArgs({
|
||||||
|
settings: {
|
||||||
|
cols: defaultCols.map(col => ({ ...col, editable: true })),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const AdditionalRowStyle = createRender(createArgs({
|
||||||
|
settings: {
|
||||||
|
cols: defaultCols.map(col => ({ ...col, editable: true })),
|
||||||
|
row: {
|
||||||
|
styleRules: [
|
||||||
|
{
|
||||||
|
condition: ({ row }) => AdditionalRowStyle.args.data[row.index].check,
|
||||||
|
applyStyle: {
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'lightgray',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const ContextMenu = createRender(createArgs({
|
||||||
|
settings: {
|
||||||
|
cols: [
|
||||||
|
{
|
||||||
|
bindTo: 'check', icon: 'ti-check', type: 'boolean', width: 50, contextMenuFactory: (col, context) => [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Check All',
|
||||||
|
action: () => {
|
||||||
|
for (const d of ContextMenu.args.data) {
|
||||||
|
d.check = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Uncheck All',
|
||||||
|
action: () => {
|
||||||
|
for (const d of ContextMenu.args.data) {
|
||||||
|
d.check = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
row: {
|
||||||
|
contextMenuFactory: (row, context) => [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Delete',
|
||||||
|
action: () => {
|
||||||
|
const idxes = context.rangedRows.map(r => r.index);
|
||||||
|
const newData = ContextMenu.args.data.filter((d, i) => !idxes.includes(i));
|
||||||
|
|
||||||
|
ContextMenu.args.data.splice(0);
|
||||||
|
ContextMenu.args.data.push(...newData);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
cells: {
|
||||||
|
contextMenuFactory: (col, row, value, context) => [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Delete',
|
||||||
|
action: () => {
|
||||||
|
for (const cell of context.rangedCells) {
|
||||||
|
ContextMenu.args.data[cell.row.index][cell.column.setting.bindTo] = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
|
@ -67,7 +67,7 @@ type RowHolder = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'event', event: GridEvent, current: GridContext): void;
|
(ev: 'event', event: GridEvent, context: GridContext): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|
Loading…
Reference in New Issue