diff --git a/docs/sw/storybook-cleanup-stage1-qa/after-index.json b/docs/sw/storybook-cleanup-stage1-qa/after-index.json new file mode 100644 index 0000000..d3311f8 --- /dev/null +++ b/docs/sw/storybook-cleanup-stage1-qa/after-index.json @@ -0,0 +1,423 @@ +[ + { + "type": "story", + "subtype": "story", + "id": "sw-header--detail-buttons", + "name": "Detail Buttons (Shared States)", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest", + "verification" + ], + "exportName": "DetailButtons" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--overview", + "name": "Overview", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Overview" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--interactive-states", + "name": "Interactive States", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "InteractiveStates" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--window-move-motion", + "name": "Window Move Motion", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "WindowMoveMotion" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--composed-controls", + "name": "Composed Controls", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "ComposedControls" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--logo-slot", + "name": "Logo Slot", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LogoSlot" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--document-dropdown", + "name": "Document Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "DocumentDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--layer-dropdown", + "name": "Layer Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LayerDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--color-dropdown", + "name": "Color Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "ColorDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--line-style-dropdown", + "name": "Line Style Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LineStyleDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--text-dimension-style-dropdown", + "name": "Text · Dimension Style Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "TextDimensionStyleDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--responsive-more", + "name": "Responsive More", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "ResponsiveMore" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--layer-detail-input", + "name": "Layer Detail · Input", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LayerDetailInput" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel", + "name": "Property Panel", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanel" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-variants", + "name": "Property Panel Variants", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelVariants" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--k-guide", + "name": "K Guide", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "KGuide" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--additional-hover", + "name": "Additional Hover", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "AdditionalHover" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-bar", + "name": "Property Bar", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyBar" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--dynamic-controls", + "name": "Dynamic Controls", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "DynamicControls" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--colorize", + "name": "Colorize", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Colorize" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--composition", + "name": "Composition (Visibility · Order)", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Composition" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-none", + "name": "Property Panel · 선택 없음", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelNone" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-all", + "name": "Property Panel · 전체 선택", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelAll" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-circle", + "name": "Property Panel · 원 1개", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelCircle" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-expanded", + "name": "Property Panel · 모두 펼침", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelExpanded" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-compare", + "name": "Property Panel · 4개 비교", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelCompare" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-shape-slot", + "name": "Property Panel · 형상 Slot", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyShapeSlot" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-fields", + "name": "Property Panel · 필드 13개", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyFields" + } +] diff --git a/docs/sw/storybook-cleanup-stage1-qa/before-index.json b/docs/sw/storybook-cleanup-stage1-qa/before-index.json new file mode 100644 index 0000000..7a0d5c7 --- /dev/null +++ b/docs/sw/storybook-cleanup-stage1-qa/before-index.json @@ -0,0 +1,498 @@ +[ + { + "type": "story", + "subtype": "story", + "id": "sw-header--detail-buttons", + "name": "Detail Buttons (Shared States)", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest", + "verification" + ], + "exportName": "DetailButtons" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--overview", + "name": "Overview", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Overview" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--default", + "name": "Default", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Default" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--controls", + "name": "Controls", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Controls" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--interactive-states", + "name": "Interactive States", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "InteractiveStates" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--responsive", + "name": "Responsive", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Responsive" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--window-move-motion", + "name": "Window Move Motion", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "WindowMoveMotion" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--composed-controls", + "name": "Composed Controls", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "ComposedControls" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--logo-slot", + "name": "Logo Slot", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LogoSlot" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--document-dropdown", + "name": "Document Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "DocumentDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--layer-dropdown", + "name": "Layer Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LayerDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--color-dropdown", + "name": "Color Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "ColorDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--line-style-dropdown", + "name": "Line Style Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LineStyleDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--text-dimension-style-dropdown", + "name": "Text · Dimension Style Dropdown", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "TextDimensionStyleDropdown" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--responsive-more", + "name": "Responsive More", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "ResponsiveMore" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--text-stroke", + "name": "Text Stroke", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "TextStroke" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--layer-detail-input", + "name": "Layer Detail · Input", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "LayerDetailInput" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--dynamic-data", + "name": "Dynamic Data", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "DynamicData" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel", + "name": "Property Panel", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanel" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-variants", + "name": "Property Panel Variants", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelVariants" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--k-guide", + "name": "K Guide", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "KGuide" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--additional-hover", + "name": "Additional Hover", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "AdditionalHover" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-bar", + "name": "Property Bar", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyBar" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--dynamic-controls", + "name": "Dynamic Controls", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "DynamicControls" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--colorize", + "name": "Colorize", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Colorize" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--composition", + "name": "Composition (Visibility · Order)", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "Composition" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-none", + "name": "Property Panel · 선택 없음", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelNone" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-all", + "name": "Property Panel · 전체 선택", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelAll" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-circle", + "name": "Property Panel · 원 1개", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelCircle" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-expanded", + "name": "Property Panel · 모두 펼침", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelExpanded" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-panel-compare", + "name": "Property Panel · 4개 비교", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyPanelCompare" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-shape-slot", + "name": "Property Panel · 형상 Slot", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyShapeSlot" + }, + { + "type": "story", + "subtype": "story", + "id": "sw-header--property-fields", + "name": "Property Panel · 필드 13개", + "title": "SW/Header", + "importPath": "./src/sw/sw-header.stories.tsx", + "componentPath": "./packages/sw/dist/index.js", + "tags": [ + "dev", + "test", + "manifest" + ], + "exportName": "PropertyFields" + } +] diff --git a/docs/sw/storybook-cleanup-stage1-qa/preservation/preservation-result.json b/docs/sw/storybook-cleanup-stage1-qa/preservation/preservation-result.json new file mode 100644 index 0000000..fcc8479 --- /dev/null +++ b/docs/sw/storybook-cleanup-stage1-qa/preservation/preservation-result.json @@ -0,0 +1,114 @@ +{ + "mode": "preservation", + "browser": "155.0.8059.80", + "checks": [ + { + "name": "required responsive width 390", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0, + "documentOverflow": 0 + } + }, + { + "name": "required responsive width 768", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0, + "documentOverflow": 0 + } + }, + { + "name": "required responsive width 1280", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0, + "documentOverflow": 0 + } + }, + { + "name": "required responsive width 1440", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0, + "documentOverflow": 0 + } + }, + { + "name": "preserve property panel none", + "status": "PASS", + "data": { + "x": 360, + "y": 204.5, + "width": 314, + "height": 256 + } + }, + { + "name": "preserve property panel all", + "status": "PASS", + "data": { + "x": 360, + "y": 204.5, + "width": 314, + "height": 361 + } + }, + { + "name": "preserve property panel circle", + "status": "PASS", + "data": { + "x": 360, + "y": 204.5, + "width": 314, + "height": 658 + } + }, + { + "name": "preserve property panel expanded", + "status": "PASS", + "data": { + "x": 360, + "y": 204.5, + "width": 314, + "height": 754 + } + }, + { + "name": "preserve window motion 1400ms", + "status": "PASS" + }, + { + "name": "window motion leave clears animations", + "status": "PASS" + }, + { + "name": "preserve K guide animation", + "status": "PASS" + }, + { + "name": "K guide leave closes", + "status": "PASS" + }, + { + "name": "preserve Colorize size", + "status": "PASS" + }, + { + "name": "preserve editable Input", + "status": "PASS" + }, + { + "name": "no browser errors", + "status": "PASS", + "data": [] + } + ], + "errors": [], + "styles": {}, + "status": "PASS" +} \ No newline at end of file diff --git a/docs/sw/storybook-cleanup-stage1-qa/result.json b/docs/sw/storybook-cleanup-stage1-qa/result.json new file mode 100644 index 0000000..e8e8094 --- /dev/null +++ b/docs/sw/storybook-cleanup-stage1-qa/result.json @@ -0,0 +1,678 @@ +{ + "checks": [ + { + "name": "33 -> 28; precisely the five requested IDs removed", + "status": "PASS", + "data": [ + { + "name": "Default", + "id": "sw-header--default" + }, + { + "name": "Controls", + "id": "sw-header--controls" + }, + { + "name": "Responsive", + "id": "sw-header--responsive" + }, + { + "name": "Text Stroke", + "id": "sw-header--text-stroke" + }, + { + "name": "Dynamic Data", + "id": "sw-header--dynamic-data" + } + ] + }, + { + "name": "all retained names, IDs, ordering and tags unchanged", + "status": "PASS" + }, + { + "name": "every retained declaration unchanged except WindowMoveMotion", + "status": "PASS", + "data": [] + }, + { + "name": "retained step section is byte-identical after newline normalization", + "status": "PASS" + }, + { + "name": "production implementation, CSS, SVG/assets and Storybook configuration unchanged", + "status": "PASS" + }, + { + "name": "render sw-header--detail-buttons", + "status": "PASS" + }, + { + "name": "render sw-header--overview", + "status": "PASS" + }, + { + "name": "render sw-header--interactive-states", + "status": "PASS" + }, + { + "name": "render sw-header--window-move-motion", + "status": "PASS" + }, + { + "name": "render sw-header--composed-controls", + "status": "PASS" + }, + { + "name": "render sw-header--logo-slot", + "status": "PASS" + }, + { + "name": "render sw-header--document-dropdown", + "status": "PASS" + }, + { + "name": "render sw-header--layer-dropdown", + "status": "PASS" + }, + { + "name": "render sw-header--color-dropdown", + "status": "PASS" + }, + { + "name": "render sw-header--line-style-dropdown", + "status": "PASS" + }, + { + "name": "render sw-header--text-dimension-style-dropdown", + "status": "PASS" + }, + { + "name": "render sw-header--responsive-more", + "status": "PASS" + }, + { + "name": "render sw-header--layer-detail-input", + "status": "PASS" + }, + { + "name": "render sw-header--property-panel", + "status": "PASS" + }, + { + "name": "render sw-header--property-panel-variants", + "status": "PASS" + }, + { + "name": "render sw-header--k-guide", + "status": "PASS" + }, + { + "name": "render sw-header--additional-hover", + "status": "PASS" + }, + { + "name": "render sw-header--property-bar", + "status": "PASS" + }, + { + "name": "render sw-header--dynamic-controls", + "status": "PASS" + }, + { + "name": "render sw-header--colorize", + "status": "PASS" + }, + { + "name": "render sw-header--composition", + "status": "PASS" + }, + { + "name": "render sw-header--property-panel-none", + "status": "PASS" + }, + { + "name": "render sw-header--property-panel-all", + "status": "PASS" + }, + { + "name": "render sw-header--property-panel-circle", + "status": "PASS" + }, + { + "name": "render sw-header--property-panel-expanded", + "status": "PASS" + }, + { + "name": "render sw-header--property-panel-compare", + "status": "PASS" + }, + { + "name": "render sw-header--property-shape-slot", + "status": "PASS" + }, + { + "name": "render sw-header--property-fields", + "status": "PASS" + }, + { + "name": "only the requested section remains", + "status": "PASS", + "data": [ + "단계별 진행 (3배 확대)" + ] + }, + { + "name": "removed live demos, frame specimens and callback logs absent", + "status": "PASS" + }, + { + "name": "nine original steps and 3x magnification preserved", + "status": "PASS", + "data": [ + { + "time": "rest", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [] + }, + { + "time": "0", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 0, + "duration": 1400 + }, + { + "state": "paused", + "time": 0, + "duration": 1400 + }, + { + "state": "paused", + "time": 0, + "duration": 1400 + } + ] + }, + { + "time": "204.8780487804878", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 204.8780487804878, + "duration": 1400 + }, + { + "state": "paused", + "time": 204.8780487804878, + "duration": 1400 + }, + { + "state": "paused", + "time": 204.8780487804878, + "duration": 1400 + } + ] + }, + { + "time": "409.7560975609756", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 409.7560975609756, + "duration": 1400 + }, + { + "state": "paused", + "time": 409.7560975609756, + "duration": 1400 + }, + { + "state": "paused", + "time": 409.7560975609756, + "duration": 1400 + } + ] + }, + { + "time": "443.9024390243902", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 443.9024390243902, + "duration": 1400 + }, + { + "state": "paused", + "time": 443.9024390243902, + "duration": 1400 + }, + { + "state": "paused", + "time": 443.9024390243902, + "duration": 1400 + } + ] + }, + { + "time": "682.9268292682926", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 682.9268292682926, + "duration": 1400 + }, + { + "state": "paused", + "time": 682.9268292682926, + "duration": 1400 + }, + { + "state": "paused", + "time": 682.9268292682926, + "duration": 1400 + } + ] + }, + { + "time": "887.8048780487804", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 887.8048780487804, + "duration": 1400 + }, + { + "state": "paused", + "time": 887.8048780487804, + "duration": 1400 + }, + { + "state": "paused", + "time": 887.8048780487804, + "duration": 1400 + } + ] + }, + { + "time": "1365.8536585365853", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 1365.8536585365853, + "duration": 1400 + }, + { + "state": "paused", + "time": 1365.8536585365853, + "duration": 1400 + }, + { + "state": "paused", + "time": 1365.8536585365853, + "duration": 1400 + } + ] + }, + { + "time": "1400", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 1400, + "duration": 1400 + }, + { + "state": "paused", + "time": 1400, + "duration": 1400 + }, + { + "state": "paused", + "time": 1400, + "duration": 1400 + } + ] + } + ] + }, + { + "name": "rest is static; timed specimens pause three 1400ms animations at their original positions", + "status": "PASS" + }, + { + "name": "live Hover motion advances with original 1400ms infinite cycle", + "status": "PASS", + "data": [ + { + "before": 0, + "after": 199.92699997154995, + "state": "running", + "duration": 1400, + "iterations": "infinite" + }, + { + "before": 0, + "after": 199.92699997154995, + "state": "running", + "duration": 1400, + "iterations": "infinite" + }, + { + "before": 0, + "after": 199.92699997154995, + "state": "running", + "duration": 1400, + "iterations": "infinite" + } + ] + }, + { + "name": "pointer held pauses motion and hides tooltip", + "status": "PASS" + }, + { + "name": "Hover leave resets live specimen", + "status": "PASS" + }, + { + "name": "Responsive More still switches the representative field and opens its dropdown", + "status": "PASS" + }, + { + "name": "Dynamic Controls removes a configured field", + "status": "PASS" + }, + { + "name": "Dynamic Controls restores a configured field", + "status": "PASS" + }, + { + "name": "host-owned document list can still grow dynamically", + "status": "PASS" + }, + { + "name": "retained fluid header layout at 390px", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0 + } + }, + { + "name": "retained fluid header layout at 768px", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0 + } + }, + { + "name": "retained fluid header layout at 1280px", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0 + } + }, + { + "name": "retained fluid header layout at 1440px", + "status": "PASS", + "data": { + "height": 49, + "overflow": 0 + } + }, + { + "name": "no browser errors", + "status": "PASS", + "data": [] + } + ], + "errors": [], + "baseCommit": "92830fe11db7f37eb6a45e8bbc6a5038ec579649", + "deleted": [ + { + "name": "Default", + "id": "sw-header--default" + }, + { + "name": "Controls", + "id": "sw-header--controls" + }, + { + "name": "Responsive", + "id": "sw-header--responsive" + }, + { + "name": "Text Stroke", + "id": "sw-header--text-stroke" + }, + { + "name": "Dynamic Data", + "id": "sw-header--dynamic-data" + } + ], + "browser": "155.0.8059.80", + "stages": [ + { + "time": "rest", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [] + }, + { + "time": "0", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 0, + "duration": 1400 + }, + { + "state": "paused", + "time": 0, + "duration": 1400 + }, + { + "state": "paused", + "time": 0, + "duration": 1400 + } + ] + }, + { + "time": "204.8780487804878", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 204.8780487804878, + "duration": 1400 + }, + { + "state": "paused", + "time": 204.8780487804878, + "duration": 1400 + }, + { + "state": "paused", + "time": 204.8780487804878, + "duration": 1400 + } + ] + }, + { + "time": "409.7560975609756", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 409.7560975609756, + "duration": 1400 + }, + { + "state": "paused", + "time": 409.7560975609756, + "duration": 1400 + }, + { + "state": "paused", + "time": 409.7560975609756, + "duration": 1400 + } + ] + }, + { + "time": "443.9024390243902", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 443.9024390243902, + "duration": 1400 + }, + { + "state": "paused", + "time": 443.9024390243902, + "duration": 1400 + }, + { + "state": "paused", + "time": 443.9024390243902, + "duration": 1400 + } + ] + }, + { + "time": "682.9268292682926", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 682.9268292682926, + "duration": 1400 + }, + { + "state": "paused", + "time": 682.9268292682926, + "duration": 1400 + }, + { + "state": "paused", + "time": 682.9268292682926, + "duration": 1400 + } + ] + }, + { + "time": "887.8048780487804", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 887.8048780487804, + "duration": 1400 + }, + { + "state": "paused", + "time": 887.8048780487804, + "duration": 1400 + }, + { + "state": "paused", + "time": 887.8048780487804, + "duration": 1400 + } + ] + }, + { + "time": "1365.8536585365853", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 1365.8536585365853, + "duration": 1400 + }, + { + "state": "paused", + "time": 1365.8536585365853, + "duration": 1400 + }, + { + "state": "paused", + "time": 1365.8536585365853, + "duration": 1400 + } + ] + }, + { + "time": "1400", + "zoom": "3", + "width": 456, + "height": 144, + "animations": [ + { + "state": "paused", + "time": 1400, + "duration": 1400 + }, + { + "state": "paused", + "time": 1400, + "duration": 1400 + }, + { + "state": "paused", + "time": 1400, + "duration": 1400 + } + ] + } + ], + "status": "PASS" +} diff --git a/docs/sw/storybook-cleanup-stage1-qa/storybook-build.txt b/docs/sw/storybook-cleanup-stage1-qa/storybook-build.txt new file mode 100644 index 0000000..fae8f7c --- /dev/null +++ b/docs/sw/storybook-cleanup-stage1-qa/storybook-build.txt @@ -0,0 +1,418 @@ + +> hm-design-system-poc@0.1.0 prebuild-storybook +> npm run check:theme-defaults && npm run build:packages + + +> hm-design-system-poc@0.1.0 check:theme-defaults +> node scripts/theme-defaults.mjs --check + +Theme defaults: 92 JSON colors / 94 contract defaults; generated outputs match + +> hm-design-system-poc@0.1.0 build:packages +> npm run build:org-chart && npm run build:ui && npm run build:center-graphic && npm run build:org-chart-react && npm run build:sw + + +> hm-design-system-poc@0.1.0 build:org-chart +> npm run build -w @hm-design/org-chart + + +> @hm-design/org-chart@0.1.0 build +> node build.mjs + +vite v8.3.0 building client environment for production... +transforming... +✓ 70 modules transformed. +rendering chunks... +computing gzip size... +dist/index.js 2,450.52 kB │ gzip: 1,648.92 kB + +✓ built in 95ms +vite v8.3.0 building client environment for production... +transforming... +✓ 70 modules transformed. +rendering chunks... +computing gzip size... +dist/orgchart.browser.js 2,456.85 kB │ gzip: 1,649.32 kB + +✓ built in 81ms + +> hm-design-system-poc@0.1.0 build:ui +> npm run build -w @hm-design/ui + + +> @hm-design/ui@0.1.0 build +> node ../../scripts/build-package.mjs ui + +vite v8.3.0 building client environment for production... +transforming... +✓ 70 modules transformed. +rendering chunks... +computing gzip size... +dist/theme/index.js 25.18 kB │ gzip: 3.98 kB +dist/index.js 120.43 kB │ gzip: 21.30 kB + +✓ built in 73ms + +> hm-design-system-poc@0.1.0 build:center-graphic +> npm run build -w @hm-design/center-graphic + + +> @hm-design/center-graphic@0.1.0 build +> node ../../scripts/build-package.mjs center-graphic + +vite v8.3.0 building client environment for production... +transforming... +✓ 145 modules transformed. +rendering chunks... +computing gzip size... +dist/style.css 88.68 kB │ gzip: 20.14 kB +dist/reference.js 0.65 kB │ gzip: 0.23 kB +dist/index.js 1.86 kB │ gzip: 0.84 kB +dist/FacilityBatch-PtW_fbvn.js 1,675.84 kB │ gzip: 276.13 kB + +✓ built in 118ms + +> hm-design-system-poc@0.1.0 build:org-chart-react +> npm run build -w @hm-design/org-chart-react + + +> @hm-design/org-chart-react@0.1.0 build +> node build.mjs + +vite v8.3.0 building client environment for production... +transforming... +✓ 5 modules transformed. +rendering chunks... +computing gzip size... +dist/index.js 0.09 kB │ gzip: 0.09 kB +dist/hm-dialog.js 4.39 kB │ gzip: 1.80 kB +dist/OrgChart-DZlWXlj3.js 10.50 kB │ gzip: 2.63 kB + +✓ built in 35ms + +> hm-design-system-poc@0.1.0 build:sw +> npm run build -w @hm-design/sw + + +> @hm-design/sw@0.1.0 build +> node build.mjs + +vite v8.3.0 building client environment for production... +transforming... +✓ 69 modules transformed. +rendering chunks... +computing gzip size... +dist/styles.css 100.39 kB │ gzip: 23.57 kB +dist/index.js 712.25 kB │ gzip: 337.98 kB + +✓ built in 111ms + +> hm-design-system-poc@0.1.0 build-storybook +> storybook build -o storybook-static --disable-telemetry + + +T Building storybook v10.6.1 +| +o Cleaning outputDir: storybook-static +| +o Loading presets +| +o Building manager.. +| +• Building open services.. +| +• Building preview.. +| +• Copying static files: public\fonts at storybook-static\fonts +| Vite vite v8.3.0 building client environment for production... +transforming... +| +• Copying static files: themes at storybook-static\themes +Found 1 warning while optimizing generated CSS: + +│ } +│ .bg-\[var\(\.\.\.\)\] { +│ background-color: var(...); +┆ ^-- Unexpected token Delim('.') +┆ +│ } +│ .bg-background { + +✓ 3101 modules transformed. +| +! Vite [lightningcss minify] 'host-context' is not recognized as a valid +| pseudo-class. Did you mean '::host-context' (pseudo-element) or is +| this a typo? +| 1322 | background-color: var(--hm-orgchart-dialog-close-hover); +| 1323 | } +| 1324 | :host-context(.dark) .hm-orgchart-employee-dialog-close:hover, +| | ^ +| 1325 | .dark .hm-orgchart-employee-dialog-close:hover { +| 1326 | background-color: color-mix(in oklab, +| var(--hm-orgchart-dialog-close-hover) 50%, transparent); +rendering chunks... +computing gzip size... +| Vite storybook-static/assets/input-26-11656-BIXt51ww.png +| 5.09 kB +| storybook-static/iframe.html +| 19.07 kB │ gzip: 5.42 kB +| storybook-static/assets/NotoSansKR-variable-k7NQXPol.ttf +| 10,414.58 kB +| storybook-static/assets/data-table-x0avmA1M.css +| 0.89 kB │ gzip: 0.32 kB +| storybook-static/assets/department-colors-preview-C8o8mgn-.css +| 1.12 kB │ gzip: 0.39 kB +| storybook-static/assets/org-chart-stories-CVVpQeIs.css +| 1.15 kB │ gzip: 0.39 kB +| storybook-static/assets/org-chart-expanded-BQqXfdmZ.css +| 1.34 kB │ gzip: 0.43 kB +| storybook-static/assets/story-page-B9TObVPB.css +| 1.74 kB │ gzip: 0.49 kB +| storybook-static/assets/designer-theme-Bv3QXGf0.css +| 2.88 kB │ gzip: 0.85 kB +| storybook-static/assets/reference-CElszmAj.css +| 3.13 kB │ gzip: 0.87 kB +| storybook-static/assets/center-stories-MLQreMPw.css +| 6.77 kB │ gzip: 1.49 kB +| storybook-static/assets/dashboard-layout-cwHZMCdB.css +| 6.90 kB │ gzip: 1.21 kB +| storybook-static/assets/engine-DrWcIejL.css +| 15.64 kB │ gzip: 3.10 kB +| storybook-static/assets/center-shared-CBSMPY7X.css +| 55.67 kB │ gzip: 10.48 kB +| storybook-static/assets/sw-header-C90CBOQd.css +| 71.39 kB │ gzip: 13.24 kB +| storybook-static/assets/style-BhhUui7W.css +| 93.80 kB │ gzip: 12.41 kB +| storybook-static/assets/iframe-BW1xNYqB.css +| 237.20 kB │ gzip: 36.15 kB +| storybook-static/assets/iframe-B2ZqwRQr.js +| 0.04 kB │ gzip: 0.06 kB +| storybook-static/assets/center-stories-Cr38slYE.js +| 0.09 kB │ gzip: 0.11 kB +| storybook-static/assets/org-chart-stories-BU9b3y-N.js +| 0.09 kB │ gzip: 0.11 kB +| storybook-static/assets/chart-column-CrDPAp-u.js +| 0.41 kB │ gzip: 0.29 kB +| storybook-static/assets/layout-grid-Dec_L8Aj.js +| 0.48 kB │ gzip: 0.28 kB +| storybook-static/assets/italic-C62xCiKB.js +| 0.58 kB │ gzip: 0.35 kB +| storybook-static/assets/org-chart-full-composition.stories-CmXC5sW1.js +| 0.59 kB │ gzip: 0.39 kB +| storybook-static/assets/org-chart-p1.stories-BSRSHtxP.js +| 0.59 kB │ gzip: 0.40 kB +| storybook-static/assets/org-chart-department-colors.stories-BJ6NN2og.js +| 0.60 kB │ gzip: 0.39 kB +| storybook-static/assets/settings-IEEhIdXT.js +| 0.62 kB │ gzip: 0.34 kB +| storybook-static/assets/org-chart-summary.stories-DUf6hNdy.js +| 0.76 kB │ gzip: 0.39 kB +| storybook-static/assets/center-information.stories-CTlvamgN.js +| 0.94 kB │ gzip: 0.63 kB +| storybook-static/assets/sample-users-CAqvNHXG.js +| 0.94 kB │ gzip: 0.67 kB +| storybook-static/assets/center-spatial.stories-Cq7GuYZv.js +| 0.97 kB │ gzip: 0.64 kB +| storybook-static/assets/rolldown-runtime-DkW27tQK.js +| 1.19 kB │ gzip: 0.67 kB +| storybook-static/assets/preload-helper-VEOc_cSF.js +| 1.33 kB │ gzip: 0.75 kB +| storybook-static/assets/center-title.stories-BBmUr86Z.js +| 1.36 kB │ gzip: 0.88 kB +| storybook-static/assets/org-chart-overview-internal.stories-xfMk8xm3.js +| 1.43 kB │ gzip: 0.68 kB +| storybook-static/assets/org-chart-cards.stories-5sVa_xK1.js +| 1.60 kB │ gzip: 0.92 kB +| storybook-static/assets/color.stories-CRESndSc.js +| 1.80 kB │ gzip: 1.03 kB +| storybook-static/assets/center-facility.stories-MbEz9XLY.js +| 1.90 kB │ gzip: 1.07 kB +| storybook-static/assets/loading-screen.stories-c2mCZt7h.js +| 1.96 kB │ gzip: 1.03 kB +| storybook-static/assets/story-board-CMOyevtm.js +| 1.99 kB │ gzip: 0.89 kB +| storybook-static/assets/skeleton.stories-Bn6sImwM.js +| 2.10 kB │ gzip: 1.00 kB +| storybook-static/assets/story-page-InLs9Vcj.js +| 2.13 kB │ gzip: 0.69 kB +| storybook-static/assets/verification-state-CRE5GvFI.js +| 2.15 kB │ gzip: 1.05 kB +| storybook-static/assets/hover-card.stories-DK6TOk7K.js +| 2.34 kB │ gzip: 1.09 kB +| storybook-static/assets/alert-dialog.stories-C3y8_aeE.js +| 2.48 kB │ gzip: 1.08 kB +| storybook-static/assets/separator.stories-DD1Lnw5I.js +| 2.56 kB │ gzip: 1.16 kB +| storybook-static/assets/dropdown-menu.stories-Ct3gPj8c.js +| 2.58 kB │ gzip: 1.29 kB +| storybook-static/assets/badge.stories-B45ffhR3.js +| 2.61 kB │ gzip: 1.23 kB +| storybook-static/assets/tooltip.stories-CdfcrH9l.js +| 2.65 kB │ gzip: 1.23 kB +| storybook-static/assets/publisher-regression.stories-BUA6jhK3.js +| 2.70 kB │ gzip: 1.14 kB +| storybook-static/assets/calendar.stories-JsGZzMU6.js +| 2.79 kB │ gzip: 1.30 kB +| storybook-static/assets/switch.stories-BkiV1juR.js +| 2.86 kB │ gzip: 1.28 kB +| storybook-static/assets/reference-CNG9Q7Qf.js +| 2.88 kB │ gzip: 1.24 kB +| storybook-static/assets/context-menu.stories-DYgUrl_5.js +| 2.95 kB │ gzip: 1.47 kB +| storybook-static/assets/center-shared-C3dIvnsE.js +| 2.96 kB │ gzip: 1.36 kB +| storybook-static/assets/scroll-area.stories-BDJ-Spvu.js +| 3.02 kB │ gzip: 1.30 kB +| storybook-static/assets/popover.stories-DpV76T6Y.js +| 3.05 kB │ gzip: 1.30 kB +| storybook-static/assets/aspect-ratio.stories-DgNz1xSz.js +| 3.06 kB │ gzip: 1.51 kB +| storybook-static/assets/typography.stories-CGPtsrfA.js +| 3.07 kB │ gzip: 1.42 kB +| storybook-static/assets/pagination.stories-CWF8okYi.js +| 3.12 kB │ gzip: 1.50 kB +| storybook-static/assets/alert.stories-oDf5co-_.js +| 3.16 kB │ gzip: 1.29 kB +| storybook-static/assets/label.stories-2WonSZOr.js +| 3.19 kB │ gzip: 1.39 kB +| storybook-static/assets/collapsible.stories-CHcI8y1q.js +| 3.19 kB │ gzip: 1.50 kB +| storybook-static/assets/drawer.stories-TOTXcbXX.js +| 3.23 kB │ gzip: 1.47 kB +| storybook-static/assets/radio-group.stories-z8I630HS.js +| 3.24 kB │ gzip: 1.47 kB +| storybook-static/assets/avatar.stories-Bsma4jmS.js +| 3.30 kB │ gzip: 1.45 kB +| storybook-static/assets/page-header.stories-CgClekDL.js +| 3.32 kB │ gzip: 1.30 kB +| storybook-static/assets/menubar.stories-C2OkGMXB.js +| 3.33 kB │ gzip: 1.39 kB +| storybook-static/assets/command.stories-BGdtj-Vw.js +| 3.33 kB │ gzip: 1.58 kB +| storybook-static/assets/center-overview.stories-BUlg6ljN.js +| 3.36 kB │ gzip: 1.77 kB +| storybook-static/assets/filter-bar.stories-kxI3Llmp.js +| 3.43 kB │ gzip: 1.72 kB +| storybook-static/assets/sheet.stories-BDx_nhob.js +| 3.51 kB │ gzip: 1.44 kB +| storybook-static/assets/progress.stories-c7TrYqeB.js +| 3.52 kB │ gzip: 1.60 kB +| storybook-static/assets/breadcrumb.stories-DWOevXaH.js +| 3.55 kB │ gzip: 1.52 kB +| storybook-static/assets/card.stories-ZUo4F81H.js +| 3.74 kB │ gzip: 1.63 kB +| storybook-static/assets/navigation-menu.stories-BmS0c7qz.js +| 3.86 kB │ gzip: 1.62 kB +| storybook-static/assets/resizable.stories-DoJps_3U.js +| 3.96 kB │ gzip: 1.46 kB +| storybook-static/assets/specimens-C49VJeZT.js +| 4.13 kB │ gzip: 1.36 kB +| storybook-static/assets/sonner.stories-vuU_t7oM.js +| 4.22 kB │ gzip: 1.83 kB +| storybook-static/assets/checkbox.stories-CZ2w2Qab.js +| 4.39 kB │ gzip: 1.66 kB +| storybook-static/assets/date-picker.stories-COb2hSCU.js +| 4.45 kB │ gzip: 1.68 kB +| storybook-static/assets/slider.stories-CwDpW7mP.js +| 4.53 kB │ gzip: 1.85 kB +| storybook-static/assets/org-chart-page-previews-DkDa-PWK.js +| 4.70 kB │ gzip: 2.05 kB +| storybook-static/assets/carousel.stories-CA_mwrsr.js +| 4.75 kB │ gzip: 1.91 kB +| storybook-static/assets/layout.stories-CQ6ojhKi.js +| 4.79 kB │ gzip: 1.92 kB +| storybook-static/assets/table.stories-13OnP4or.js +| 4.86 kB │ gzip: 2.02 kB +| storybook-static/assets/combobox.stories-7-ze7vBq.js +| 5.03 kB │ gzip: 2.06 kB +| storybook-static/assets/accordion.stories-CE5xTSQ-.js +| 5.05 kB │ gzip: 1.81 kB +| storybook-static/assets/OrgChart-DZlWXlj3-DpBLtOar.js +| 5.35 kB │ gzip: 1.94 kB +| storybook-static/assets/dialog.stories-BtscPLmz.js +| 5.53 kB │ gzip: 2.13 kB +| storybook-static/assets/toggle.stories-DWnnq7g_.js +| 5.81 kB │ gzip: 2.12 kB +| storybook-static/assets/data-table.stories-CV4Eyfkw.js +| 5.92 kB │ gzip: 2.51 kB +| storybook-static/assets/textarea.stories-q50rAgK3.js +| 5.99 kB │ gzip: 2.43 kB +| storybook-static/assets/runtime-loader.stories-DuMZGCVT.js +| 6.18 kB │ gzip: 2.45 kB +| storybook-static/assets/toggle-group.stories-BTaGOcrf.js +| 6.57 kB │ gzip: 2.23 kB +| storybook-static/assets/react-Q1GcV6wX.js +| 7.87 kB │ gzip: 3.01 kB +| storybook-static/assets/input.stories-Co1wru0X.js +| 8.32 kB │ gzip: 3.05 kB +| storybook-static/assets/button.stories-CW2ZQ7Bp.js +| 9.65 kB │ gzip: 3.62 kB +| storybook-static/assets/select.stories-CAX3tTcq.js +| 10.52 kB │ gzip: 3.39 kB +| storybook-static/assets/tabs.stories-DZ_x3GeH.js +| 11.57 kB │ gzip: 4.13 kB +| storybook-static/assets/org-chart.stories-D49__YqK.js +| 12.54 kB │ gzip: 4.15 kB +| storybook-static/assets/designer-theme.stories-D8Hrex2Y.js +| 14.62 kB │ gzip: 5.52 kB +| storybook-static/assets/gnb.stories-Bz0tX0qH.js +| 16.56 kB │ gzip: 5.83 kB +| storybook-static/assets/theme-CZw7CMzf.js +| 18.61 kB │ gzip: 3.18 kB +| storybook-static/assets/lnb.stories-DHeUgKcQ.js +| 23.06 kB │ gzip: 6.43 kB +| storybook-static/assets/dashboard-layout.stories-D3EPoHnA.js +| 23.84 kB │ gzip: 6.25 kB +| storybook-static/vite-inject-mocker-entry.js +| 27.84 kB │ gzip: 9.66 kB +| storybook-static/assets/reference-data-Dp4dBiCx.js +| 40.42 kB │ gzip: 9.43 kB +| storybook-static/assets/runtime-theme.stories-o-w95Yhu.js +| 61.92 kB │ gzip: 11.60 kB +| storybook-static/assets/org-chart-expanded.stories-DwIuuCDG.js +| 79.03 kB │ gzip: 10.07 kB +| storybook-static/assets/react-18-DPql6C9x.js +| 207.62 kB │ gzip: 65.12 kB +| storybook-static/assets/core-component-preview-qVlFRdYj.js +| 258.40 kB │ gzip: 146.05 kB +| storybook-static/assets/sw-header.stories-rIXaAc8o.js +| 758.58 kB │ gzip: 357.47 kB +| storybook-static/assets/reference-CBHPHHCT.js +| 1,644.48 kB │ gzip: 270.35 kB +| storybook-static/assets/iframe-DVD1nTdY.js +| 1,754.05 kB │ gzip: 503.60 kB +| storybook-static/assets/style-CNeiB0x2.js +| 2,359.94 kB │ gzip: 1,631.23 kB + +| +! Vite [plugin builtin:vite-reporter] +| (!) Some chunks are larger than 500 kB after minification. Consider: +| - Using dynamic import() to code-split the application +| - Use build.rolldownOptions.output.codeSplitting to improve chunking: +| ]8;;https://rolldown.rs/reference/OutputOptions.codeSplittinghttps://rolldown.rs/reference/OutputOptions.codeSplitting]8;; +| - Adjust chunk size limit for this warning via +| build.chunkSizeWarningLimit. +| Vite ✓ built in 3.88s +| +! Vite [PLUGIN_TIMINGS] JavaScript callbacks ran for 3.4s of this 3.9s +| build (87%). +| The slowest callbacks, timed inside each callback (the wait before a +| callback starts is excluded, the time it awaits is included): +| - plugin storybook:react-docgen-plugin transform (60%, 2.3s, 3101 +| calls) +| Additional callback time came from the callbacks below and from +| callbacks under 1s. +| 3 callbacks are listed without a time. Their calls overlapped, so the +| time inside one call includes work from other calls. To find their +| cost, profile the build with `node --cpu-prof`: +| - plugin vite:asset load (31 calls) +| - plugin @tailwindcss/vite:generate:build transform (19 calls) +| - plugin vite:css transform (19 calls) +| See ]8;;https://rolldown.rs/reference/InputOptions.checks#bundlertimingshttps://rolldown.rs/reference/InputOptions.checks#bundlertimings]8;; +| for more details. + +| +o Output directory: D:/디자인시스템/HMDesign-SW/storybook-static +| +— Storybook build completed successfully diff --git a/docs/sw/storybook-cleanup-stage1-qa/validation-summary.json b/docs/sw/storybook-cleanup-stage1-qa/validation-summary.json new file mode 100644 index 0000000..a114b9e --- /dev/null +++ b/docs/sw/storybook-cleanup-stage1-qa/validation-summary.json @@ -0,0 +1,32 @@ +{ + "storybookBuild": { + "command": "npm.cmd run build-storybook", + "exitCode": 0, + "status": "PASS", + "log": "storybook-build.txt" + }, + "swTypecheck": { + "command": "npm.cmd run typecheck:sw", + "exitCode": 0, + "status": "PASS" + }, + "storyTypecheck": { + "command": "npm.cmd exec -- tsc -p tsconfig.app.json --noEmit", + "exitCode": 0, + "status": "PASS" + }, + "browser": { + "status": "PASS", + "checks": 49 + }, + "preservation": { + "status": "PASS", + "checks": 15 + }, + "warnings": [ + "CSS optimizer: background-color: var(...) generated utility", + "OrgChart :host-context minifier warnings", + "Vite chunk size warnings" + ], + "scope": "STORYBOOK_ONLY; no new application screen; AI screen generation guard not applicable" +} diff --git a/docs/sw/storybook-cleanup-stage1-qa/window-move-motion.png b/docs/sw/storybook-cleanup-stage1-qa/window-move-motion.png new file mode 100644 index 0000000..895918a Binary files /dev/null and b/docs/sw/storybook-cleanup-stage1-qa/window-move-motion.png differ diff --git a/docs/sw/sw-storybook-cleanup-stage1-2026-10-19.md b/docs/sw/sw-storybook-cleanup-stage1-2026-10-19.md new file mode 100644 index 0000000..8dc8fb6 --- /dev/null +++ b/docs/sw/sw-storybook-cleanup-stage1-2026-10-19.md @@ -0,0 +1,67 @@ +# SW Storybook 2차 정리 1단계 — 지정 항목 삭제 + +- 판정: PASS. 범위는 `STORYBOOK_ONLY`이며 신규 업무 화면 생성이 아니므로 AI 화면 생성 Guard는 적용하지 않았습니다. +- 시작 상태: `D:\디자인시스템\HMDesign-SW`, `feature/sw-package`, `92830fe11db7f37eb6a45e8bbc6a5038ec579649`, Working Tree clean, upstream 대비 기존 로컬 Commit 2개. +- 사용자 요청에 따라 현재 브랜치에서 로컬 Commit만 수행합니다. Push·PR·다음 정리 단계는 수행하지 않습니다. + +## 적용 내용 + +삭제한 독립 Story 5개: + +- Responsive — `sw-header--responsive` +- Text Stroke — `sw-header--text-stroke` +- Dynamic Data — `sw-header--dynamic-data` +- Default — `sw-header--default` +- Controls — `sw-header--controls` + +Window Move Motion(`sw-header--window-move-motion`)에는 **단계별 진행 (3배 확대)** 섹션만 남겼습니다. 페이지 제목은 유지했고 다른 시연에 대한 머리말 설명은 제거했습니다. + +제거한 시연 섹션: + +- GIF 주요 3상태 (정적, 3배 확대) +- 실제 Hover · 창 이동 · 클릭 (1920) +- 이동 완료 실제 배치 (1920, 고정) +- 헤더 1080 미만 (1079 고정 · 768 실제 Hover) +- Reduced Motion + +해당 Story에서만 사용하는 `MotionDemo`, `RESPONSIVE_WIDTHS`, `DynamicDataDemo` 및 전용 타입·상수·목록 조작 함수도 제거했습니다. 공유 Fixture·Callback·함수는 유지했습니다. + +## 보존 및 검증 + +- 수정 전 현재 소스에 Storybook index 명령을 실행해 33개를 확보했습니다. 기존 `storybook-static`은 최신 소스와 목록이 달라 기준으로 사용하지 않았습니다. +- 최종 Build index는 28개입니다. 삭제 차이는 위 5개와 정확히 일치하고 나머지 ID·이름·순서·태그는 동일합니다. verification 태그도 그대로입니다. +- `Responsive More`, `Dynamic Controls`를 포함한 남은 Story 28개가 실제 Chrome에서 렌더링됩니다. +- 시작 Commit과 AST 선언 텍스트를 비교해 `WindowMoveMotion` 외 모든 남은 선언이 동일함을 확인했습니다. 단계별 섹션 JSX·`MOTION_STAGES`·`motionTime`·`MotionAt`·`MotionSpecimen`도 그대로입니다. +- 단계 9개, `zoom: 3` 및 실제 456×144px 표본, 정지 표본 3개 애니메이션의 원래 시간 위치, 실제 Hover 재생·1400ms 무한 반복·Pointer 누름 중 정지·Tooltip 숨김·이탈 복귀를 확인했습니다. +- More의 대표 필드 전환·Dropdown 열림, Dynamic Controls 항목 제거·복원 및 문서 목록 추가를 확인했습니다. +- 기존 보존 검증에서 390/768/1280/1440px Header overflow·높이, 속성창 크기, K 가이드, Colorize 및 편집 Input도 통과했습니다. +- Header 구현·공개 API·패키지 CSS·Story CSS·SVG/이미지·Storybook 설정은 시작 Commit과 동일합니다. 실제 반응형·텍스트 외곽선·동적 데이터 기능과 Controls 관련 설정은 유지됩니다. + +실행 결과: + +- `npm.cmd run build-storybook`: PASS. 패키지 사전 빌드 포함. +- `npm.cmd run typecheck:sw`: PASS. +- `npm.cmd exec -- tsc -p tsconfig.app.json --noEmit`: PASS. Story 파일 포함. +- `node packages/sw/tests/storybook-cleanup-stage1.browser.mjs`: **49/49 PASS**, 브라우저 오류 0. +- `node packages/sw/tests/detail-buttons.browser.mjs preservation docs/sw/storybook-cleanup-stage1-qa/preservation`: **15/15 PASS**, 브라우저 오류 0. +- `git diff --check`: PASS. + +Build에는 생성된 `var(...)` 유틸리티, OrgChart `:host-context`, chunk 크기 관련 경고가 있습니다. Build는 성공했으며 해당 코드·설정은 이번 변경 범위 밖입니다. + +검증 범위는 Chrome의 변경 Story 및 관련 보존 동작입니다. 나머지 모든 Story의 모든 상호작용과 Firefox 전체 회귀 검사는 이번에 재실행하지 않았습니다(`NOT VERIFIED`). + +## 테스트 참조와 증거 + +기존 `detail-buttons.browser.mjs`의 삭제된 Default/Controls 렌더링 참조를 Overview/Composition으로 옮겼고, Story 목록 비교에서 승인된 5개 삭제만 허용하도록 수정했습니다. 기존 baseline·검증 파일·증거는 삭제하거나 덮어쓰지 않았습니다. 전체 `verify` 모드의 Header 위치 비교는 대체 Story 기준 baseline이 필요하므로 필요 시 **새 증거 디렉터리**에 `baseline` 모드로 먼저 확보합니다. 이번에는 영향을 받는 `preservation` 모드와 범위 전용 검증을 실행했습니다. + +새 증거: + +- [수정 전 33개 목록](storybook-cleanup-stage1-qa/before-index.json) +- [수정 후 28개 목록](storybook-cleanup-stage1-qa/after-index.json) +- [범위 전용 검증 결과](storybook-cleanup-stage1-qa/result.json) +- [기존 보존 검증 결과](storybook-cleanup-stage1-qa/preservation/preservation-result.json) +- [통합 검증 요약](storybook-cleanup-stage1-qa/validation-summary.json) +- [Storybook Build 기록](storybook-cleanup-stage1-qa/storybook-build.txt) +- [정리 후 Window Move Motion 화면](storybook-cleanup-stage1-qa/window-move-motion.png) + +이전 1차 정리 보고서와 과거 검증 기록은 당시 상태를 보여 주는 기록으로 보존했습니다. diff --git a/packages/sw/tests/detail-buttons.browser.mjs b/packages/sw/tests/detail-buttons.browser.mjs index 4f66e96..ed16aed 100644 --- a/packages/sw/tests/detail-buttons.browser.mjs +++ b/packages/sw/tests/detail-buttons.browser.mjs @@ -42,7 +42,7 @@ try { await page.locator('[data-detail-row="문자스타일 상세"] [data-detail-case="hover"] button').hover() await page.screenshot({path:path.join(output,'comparison-pointer-hover.png'),fullPage:true}) } else if (mode === 'preservation') { - await goto('controls') + await goto('composition') for(const width of [390,768,1280,1440]){ await page.setViewportSize({width,height:1000}) const layout=await page.locator('header.hm-sw-header').first().evaluate(h=>({height:h.getBoundingClientRect().height,overflow:h.scrollWidth-h.clientWidth,documentOverflow:document.documentElement.scrollWidth-document.documentElement.clientWidth})) @@ -54,7 +54,7 @@ try { const box=await page.locator('.hm-sw-property').first().boundingBox() check(`preserve property panel ${id}`,box.width===314&&box.height===height,box) } - await goto('controls') + await goto('composition') const motion=page.locator('[data-sw-window-move]').first();await motion.hover() check('preserve window motion 1400ms',await motion.evaluate(e=>e.getAnimations({subtree:true}).length===3&&e.getAnimations({subtree:true}).every(a=>a.effect.getTiming().duration===1400))) await page.mouse.move(1,900);check('window motion leave clears animations',await motion.evaluate(e=>e.getAnimations({subtree:true}).length===0)) @@ -70,7 +70,8 @@ try { const ids = Object.values(index.entries).filter(e => e.title === 'SW/Header' && e.type === 'story').map(e => e.id) report.storyIds = ids if (mode === 'baseline') await writeFile(path.join(output, 'baseline-story-ids.json'), JSON.stringify(ids)) - for (const story of ['default', 'controls']) { + // These retained examples cover fixed-width and fluid headers after the two Args demos were retired. + for (const story of ['overview', 'composition']) { await goto(story) for (const width of [1920,1800,1440,1180,1080,900,768,640,520,390]) { await page.setViewportSize({ width, height:1000 }) @@ -94,9 +95,11 @@ try { await writeFile(path.join(output,'baseline.json'),JSON.stringify(snapshots,null,2)) } else { const before=JSON.parse(await readFile(path.join(output,'baseline.json'),'utf8')) - for(const key of Object.keys(before).filter(k=>!k.startsWith('text'))) check(`unchanged header ${key}`,JSON.stringify(before[key])===JSON.stringify(snapshots[key])) + for(const key of Object.keys(snapshots).filter(k=>!k.startsWith('text'))) check(`unchanged header ${key} (capture a current baseline for replacement fixtures)`,JSON.stringify(before[key])===JSON.stringify(snapshots[key])) const oldIds=JSON.parse(await readFile(path.join(output,'baseline-story-ids.json'),'utf8')) - check('all previous 31 stories retained',oldIds.length===31&&oldIds.every(id=>ids.includes(id)),{before:oldIds.length,after:ids.length}) + const retiredIds=['default','controls','responsive','text-stroke','dynamic-data'].map(id=>`sw-header--${id}`) + const retainedIds=oldIds.filter(id=>!retiredIds.includes(id)) + check('retained stories remain; only the five approved demos are absent',ids.length===28&&retainedIds.every(id=>ids.includes(id))&&retiredIds.every(id=>!ids.includes(id)),{before:oldIds.length,after:ids.length}) for(const id of ids){await goto(id.replace('sw-header--',''));check(`render ${id}`,!(await page.locator('.sb-errordisplay').isVisible()))} await goto('composition') const presets=['기본 전체','구성 A','구성 B (레이어·선스타일)','구성 C (로고만)','파일 목록 제거','레이어 제거','색상 제거','스타일 그룹 제거','여러 메뉴 제거','순서 변경','숨김 + 순서 변경'] diff --git a/packages/sw/tests/storybook-cleanup-stage1.browser.mjs b/packages/sw/tests/storybook-cleanup-stage1.browser.mjs new file mode 100644 index 0000000..e83ab76 --- /dev/null +++ b/packages/sw/tests/storybook-cleanup-stage1.browser.mjs @@ -0,0 +1,148 @@ +// Scoped verification for the five approved Story removals; serves the production build locally. +// Usage: node packages/sw/tests/storybook-cleanup-stage1.browser.mjs [evidence-dir] +import { createRequire } from 'node:module' +import { readFile, writeFile, mkdir } from 'node:fs/promises' +import { execFileSync } from 'node:child_process' +import path from 'node:path' +import http from 'node:http' +import { parse } from '@babel/parser' + +const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-cleanup-stage1-qa') +await mkdir(out, { recursive: true }) +const report = { checks: [], errors: [], baseCommit: '92830fe11db7f37eb6a45e8bbc6a5038ec579649' } +const check = (name, ok, data) => { + report.checks.push({ name, status: ok ? 'PASS' : 'FAIL', data }) + console.log(ok ? 'PASS' : 'FAIL', name) +} +const retired = ['responsive', 'text-stroke', 'dynamic-data', 'default', 'controls'].map(id => `sw-header--${id}`) +const before = JSON.parse(await readFile(path.join(out, 'before-index.json'), 'utf8')) +const after = Object.values(JSON.parse(await readFile('storybook-static/index.json', 'utf8')).entries) + .filter(e => e.type === 'story' && e.title === 'SW/Header') +await writeFile(path.join(out, 'after-index.json'), JSON.stringify(after, null, 2) + '\n') +report.deleted = before.filter(e => !after.some(a => a.id === e.id)).map(e => ({ name: e.name, id: e.id })) +check('33 -> 28; precisely the five requested IDs removed', before.length === 33 && after.length === 28 && + report.deleted.length === 5 && retired.every(id => report.deleted.some(e => e.id === id)), report.deleted) +check('all retained names, IDs, ordering and tags unchanged', JSON.stringify(before.filter(e => !retired.includes(e.id)).map(e => [e.id, e.name, e.tags])) === + JSON.stringify(after.map(e => [e.id, e.name, e.tags]))) + +// Compare declaration text with the starting commit, including every retained fixture/helper. +const file = 'src/sw/sw-header.stories.tsx' +const original = execFileSync('git', ['show', `${report.baseCommit}:${file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n') +const current = (await readFile(file, 'utf8')).replaceAll('\r\n', '\n') +const declarations = text => { + return parse(text, { sourceType: 'module', plugins: ['typescript', 'jsx'] }).program.body.map(statement => { + const n = statement.type === 'ExportNamedDeclaration' ? statement.declaration : statement + return { + name: n.type === 'VariableDeclaration' ? n.declarations.map(d => d.id.name).join(',') : + n.type === 'ImportDeclaration' ? `import:${n.source.value}` : n.id?.name ?? n.type, + text: text.slice(statement.start, statement.end), + } + }) +} +const oldDeclarations = new Map(declarations(original).map(d => [d.name, d.text])) +const changed = declarations(current).filter(d => d.name !== 'WindowMoveMotion' && oldDeclarations.get(d.name) !== d.text) +check('every retained declaration unchanged except WindowMoveMotion', changed.length === 0, changed.map(d => d.name)) +const section = text => text.match(//)?.[0] +check('retained step section is byte-identical after newline normalization', !!section(original) && section(original) === section(current)) +const productionDiff = execFileSync('git', ['diff', report.baseCommit, '--', 'packages/sw/src', 'src/sw/sw-stories.css', 'src/sw/assets', '.storybook'], { encoding: 'utf8' }) +check('production implementation, CSS, SVG/assets and Storybook configuration unchanged', productionDiff === '') + +const root = path.resolve('storybook-static') +const mime = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.svg': 'image/svg+xml', '.ttf': 'font/ttf', '.png': 'image/png' } +const server = http.createServer(async (req, res) => { + try { + const pathname = new URL(req.url, 'http://localhost').pathname + const file = path.resolve(root, '.' + decodeURIComponent(pathname === '/' ? '/index.html' : pathname)) + if (path.relative(root, file).startsWith('..')) return res.writeHead(403).end() + res.setHeader('Content-Type', mime[path.extname(file)] ?? 'application/octet-stream') + res.end(await readFile(file)) + } catch { res.writeHead(404).end() } +}) +await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)) +const base = `http://127.0.0.1:${server.address().port}` +const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright') +let browser +try { + browser = await chromium.launch({ headless: true, executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' }) + report.browser = browser.version() + const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } }) + page.on('pageerror', e => report.errors.push(e.message)) + page.on('console', m => { if (m.type() === 'error') report.errors.push(m.text()) }) + const goto = async id => { + await page.goto(`${base}/iframe.html?id=${id.startsWith('sw-header--') ? id : `sw-header--${id}`}&viewMode=story`) + await page.locator('.hm-sw-header, .hm-sw-theme').first().waitFor() + await page.evaluate(() => document.fonts.ready) + await page.mouse.move(1, 1) + } + for (const entry of after) { + await goto(entry.id) + check(`render ${entry.id}`, !(await page.locator('.sb-errordisplay').isVisible())) + } + + await goto('window-move-motion') + const titles = await page.locator('section > header h2').allTextContents() + check('only the requested section remains', JSON.stringify(titles) === JSON.stringify(['단계별 진행 (3배 확대)']), titles) + check('removed live demos, frame specimens and callback logs absent', await page.locator('[data-frame-width], [data-callback-log]').count() === 0) + const stages = await page.locator('[data-motion-time]').evaluateAll(elements => elements.map(e => { + const zoom = e.querySelector('.sw-story-zoom'), motion = e.querySelector('[data-sw-window-move]') + const box = zoom.getBoundingClientRect() + return { time: e.dataset.motionTime, zoom: getComputedStyle(zoom).zoom, width: box.width, height: box.height, + animations: motion.getAnimations({ subtree: true }).map(a => ({ state: a.playState, time: a.currentTime, duration: a.effect.getTiming().duration })) } + })) + report.stages = stages + const expected = ['rest', ...[0, 240, 480, 520, 800, 1040, 1600, 1640].map(t => String(t * 1400 / 1640))] + check('nine original steps and 3x magnification preserved', stages.length === 9 && stages.every((s, i) => s.time === expected[i] && Number(s.zoom) === 3 && s.width === 456 && s.height === 144), stages) + check('rest is static; timed specimens pause three 1400ms animations at their original positions', stages[0].animations.length === 0 && stages.slice(1).every(s => s.animations.length === 3 && s.animations.every(a => a.state === 'paused' && a.duration === 1400 && Math.abs(a.time - Number(s.time)) < 0.01))) + await page.screenshot({ path: path.join(out, 'window-move-motion.png'), fullPage: true }) + const motion = page.locator('[data-motion-time="rest"] [data-sw-window-move]') + await motion.hover() + const timing = await motion.evaluate(async e => { + const animations = e.getAnimations({ subtree: true }) + const before = animations.map(a => a.currentTime) + const started = performance.now() + await new Promise(resolve => { const tick = () => performance.now() - started >= 180 ? resolve() : requestAnimationFrame(tick); requestAnimationFrame(tick) }) + return animations.map((a, i) => ({ before: before[i], after: a.currentTime, state: a.playState, duration: a.effect.getTiming().duration, iterations: a.effect.getTiming().iterations === Infinity ? 'infinite' : a.effect.getTiming().iterations })) + }) + check('live Hover motion advances with original 1400ms infinite cycle', timing.length === 3 && timing.every(a => a.state === 'running' && a.after > a.before && a.duration === 1400 && a.iterations === 'infinite'), timing) + await page.mouse.down() + check('pointer held pauses motion and hides tooltip', await motion.evaluate(e => e.getAnimations({ subtree: true }).every(a => a.playState === 'paused') && getComputedStyle(e.querySelector('[role="tooltip"]')).visibility === 'hidden')) + await page.mouse.up() + await page.mouse.move(1, 1) + check('Hover leave resets live specimen', await motion.evaluate(e => e.getAnimations({ subtree: true }).length === 0)) + + await goto('responsive-more') + const header = page.locator('[data-frame-width="1440"] header.hm-sw-header').first() + await header.getByRole('button', { name: '더보기', exact: true }).click() + await header.locator('[role="menuitem"][data-menu="line-style"]').click() + check('Responsive More still switches the representative field and opens its dropdown', await header.locator('.hm-sw-header__line-menu').count() > 0 && await header.locator('.hm-sw-header__line-menu').isVisible()) + await page.keyboard.press('Escape') + + await goto('dynamic-controls') + await page.getByRole('checkbox', { name: '구성 color', exact: true }).uncheck() + check('Dynamic Controls removes a configured field', await page.locator('header.hm-sw-header [data-control="color"], header.hm-sw-header [data-menu="color"]').count() === 0) + await page.getByRole('checkbox', { name: '구성 color', exact: true }).check() + check('Dynamic Controls restores a configured field', await page.locator('header.hm-sw-header [data-menu="color"]').count() > 0) + await page.getByRole('button', { name: '구성 초기화', exact: true }).click() + const documents = page.locator('header.hm-sw-header .hm-sw-header__document-button') + await documents.click() + await page.getByRole('button', { name: '+ New', exact: true }).click() + await documents.click() + check('host-owned document list can still grow dynamically', await page.getByText('새 문서 1', { exact: true }).count() > 0) + + await goto('composition') + for (const width of [390, 768, 1280, 1440]) { + await page.setViewportSize({ width, height: 1000 }) + const geometry = await page.locator('header.hm-sw-header').evaluate(e => ({ height: e.getBoundingClientRect().height, overflow: e.scrollWidth - e.clientWidth })) + check(`retained fluid header layout at ${width}px`, geometry.height === 49 && geometry.overflow === 0, geometry) + } + check('no browser errors', report.errors.length === 0, report.errors) +} catch (error) { + check('suite completes', false, error.stack) +} finally { + if (browser) await browser.close() + await new Promise(resolve => server.close(resolve)) + report.status = report.checks.every(c => c.status === 'PASS') ? 'PASS' : 'FAIL' + await writeFile(path.join(out, 'result.json'), JSON.stringify(report, null, 2) + '\n') + console.log(JSON.stringify({ status: report.status, checks: report.checks.length, errors: report.errors })) + process.exitCode = report.status === 'PASS' ? 0 : 1 +} diff --git a/src/sw/sw-header.stories.tsx b/src/sw/sw-header.stories.tsx index a13e264..9b7521c 100644 --- a/src/sw/sw-header.stories.tsx +++ b/src/sw/sw-header.stories.tsx @@ -198,14 +198,6 @@ export const Overview: Story = { ), } -export const Default: Story = { - render: args => , -} - -export const Controls: Story = { - render: args => , -} - export const InteractiveStates: Story = { name: "Interactive States", parameters: { controls: { disable: true } }, @@ -260,26 +252,6 @@ export const InteractiveStates: Story = { ), } -const RESPONSIVE_WIDTHS = [1920, 1800, 1799, 1770, 1600, 1440, 1280, 1180, 1179, 1080, 1079, 900, 899, 768, 640, 639, 560, 390] - -export const Responsive: Story = { - parameters: { controls: { disable: true } }, - render: () => ( - - - {RESPONSIVE_WIDTHS.map(width => ( - - - - ))} - - ), -} - /** Preserve GIF phase ratios/positions, with the user-requested 1640 -> 1400ms speed change. */ const motionTime = (gifTime: number) => gifTime * 1400 / 1640 const MOTION_STAGES = [ @@ -320,58 +292,12 @@ function MotionSpecimen({ time }: { time?: number }) { ) } -/** Live header with a callback / animation log, to check drag and clicks under the motion. */ -function MotionDemo({ width }: { width: number }) { - const [log, setLog] = useState([]) - const ref = useRef(null) - const add = (line: string) => setLog(lines => [...lines.slice(-9), line]) - useEffect(() => { - const area = ref.current?.querySelector(".hm-sw-header__motion") - if (!area) return - // One tooltip animation per play stands for the whole motion. - const listen = (type: string, line: string) => { - const handler = (event: Event) => { if ((event as AnimationEvent).animationName.endsWith("-tooltip")) add(line) } - area.addEventListener(type, handler) - return () => area.removeEventListener(type, handler) - } - const cleanups = [listen("animationstart", "motion start"), listen("animationiteration", "motion cycle"), listen("animationend", "motion end"), listen("animationcancel", "motion reset")] - return () => cleanups.forEach(cleanup => cleanup()) - }, []) - return ( - <> -

기록: {log.length ? log.join(" → ") : "없음"}

-
- - { console.info("[SWHeader] windowMoveStart"); add("onWindowMoveStart") }} - onMinimize={() => { callbacks.onMinimize(); add("onMinimize") }} - onClose={() => { callbacks.onClose(); add("onClose") }} - /> - -
- - ) -} - export const WindowMoveMotion: Story = { name: "Window Move Motion", parameters: { controls: { disable: true } }, render: () => ( - - -
- - - -
-
+
{MOTION_STAGES.map(stage => ( @@ -382,21 +308,6 @@ export const WindowMoveMotion: Story = { ))}
- - - - - - - -
- - -
-
- -

OS 설정을 켠 뒤 위 '실제 Hover' 예제에 마우스를 올려 확인합니다. Storybook은 이 미디어 조건을 강제로 켤 수 없습니다.

-
), } @@ -1093,47 +1004,6 @@ export const ResponsiveMore: Story = { ), } -export const TextStroke: Story = { - name: "Text Stroke", - parameters: { controls: { disable: true } }, - render: () => ( - - - - - - -
- - - - - - - - - - - - - - - - - -
-
- - - -
- ), -} - /** Host-owned detail values for the editable input (the detail popup itself is not designed yet). */ function InputDemo() { const [value, setValue] = useState("4.0526") @@ -1229,135 +1099,6 @@ export const LayerDetailInput: Story = { ), } -/* Dynamic data: every list is host data. Adding, removing, renaming, revaluing and reordering items - needs no component change; ids keep each row's state; a removed current item leaves no selection. */ -type DynamicLists = { - layers: SWHeaderLayer[] - colors: SWHeaderColorOption[] - userColors: SWHeaderColorOption[] - lineTypes: SWHeaderLineType[] - lineWeights: SWHeaderLineWeight[] - textStyles: SWHeaderTextStyleOption[] - dimensionStyles: SWHeaderDimensionStyleOption[] - documents: SWHeaderDocument[] -} -type DynamicKey = keyof DynamicLists -const DYNAMIC_INITIAL: DynamicLists = { - layers: SAMPLE_LAYERS.slice(0, 4), - colors: FIGMA_COLORS, - userColors: FIGMA_USER_COLORS, - lineTypes: FIGMA_LINE_TYPES, - lineWeights: FIGMA_LINE_WEIGHTS, - textStyles: FIGMA_TEXT_STYLES, - dimensionStyles: FIGMA_DIMENSION_STYLES, - documents: CURRENT_DOCUMENT, -} -const DYNAMIC_LABELS: Record = { - layers: "레이어", colors: "기본 색상", userColors: "사용자 색상", lineTypes: "선 종류", lineWeights: "가중치", - textStyles: "문자스타일", dimensionStyles: "치수스타일", documents: "문서", -} -/** New sample item of each list (`n` keeps ids unique). */ -const DYNAMIC_FACTORY: { [K in DynamicKey]: (n: number) => DynamicLists[K][number] } = { - layers: n => ({ id: `new-layer-${n}`, name: `New-Layer-${n}`, color: "#ffa500" }), - colors: n => ({ id: `color-${n}`, color: `hsl(${(n * 67) % 360} 80% 55%)`, label: `추가 색상 ${n}` }), - userColors: n => ({ id: `user-color-${n}`, color: `hsl(${(n * 83) % 360} 70% 60%)`, label: `사용자 색상 추가 ${n}` }), - lineTypes: n => ({ id: `line-${n}`, name: `DASH-${n}`, pattern: [12, 4, 12, 4] }), - lineWeights: n => ({ id: `weight-${n}`, name: `${(0.05 * n).toFixed(2)} mm`, value: (0.05 * n).toFixed(2) }), - textStyles: n => ({ id: `text-${n}`, font: "굴림", name: `Text-${n}` }), - dimensionStyles: n => ({ id: `dim-${n}`, name: `DIM-${n}` }), - documents: n => ({ id: `doc-${n}`, name: `Sample-New-${n}.dwg` }), -} -const renameFirst = (list: T[]) => - list.map((item, index) => (index !== 0 ? item : "name" in item ? { ...item, name: `${item.name}*` } : { ...item, label: `${item.label ?? ""}*` })) - -function DynamicDataDemo() { - const [lists, setLists] = useState(DYNAMIC_INITIAL) - const [active, setActive] = useState({ layer: "layer-0", lineType: "continuous", lineWeight: "w-default", textStyle: "standard", dimensionStyle: "standard", document: "doc-current" }) - const [lineStyle, setLineStyle] = useState(figmaArgs.lineStyle!) - const [log, setLog] = useState([]) - const counter = useRef(0) - const add = (line: string) => setLog(lines => [...lines.slice(-9), line]) - const update = (key: K, next: (list: DynamicLists[K]) => DynamicLists[K], line: string) => { - setLists(current => ({ ...current, [key]: next(current[key]) })) - add(line) - } - const keys = Object.keys(lists) as DynamicKey[] - const currentDocument = lists.documents.find(item => item.id === active.document) - return ( - <> -
- {keys.map(key => ( -
- {DYNAMIC_LABELS[key]} ({lists[key].length}) - - - - -
- ))} -
- 값 · 상태 변경 - - - -
-
-

기록: {log.length ? log.join(" → ") : "없음"}

-
{`active: ${JSON.stringify(active)}`}
- - { add(`onDocumentSelect(${document.id})`); setActive(current => ({ ...current, document: document.id })) }} - onDocumentClose={document => update("documents", list => list.filter(item => item.id !== document.id), `onDocumentClose(${document.id})`)} - layers={lists.layers} - activeLayerId={active.layer} - onLayerSelect={layer => { add(`onLayerSelect(${layer.id})`); setActive(current => ({ ...current, layer: layer.id })) }} - onLayerVisibilityChange={(layer, next) => update("layers", list => list.map(item => (item.id === layer.id ? { ...item, visible: next } : item)), `onLayerVisibilityChange(${layer.id}, ${next})`)} - colors={lists.colors} - userColors={lists.userColors} - onColorSelect={option => add(`onColorSelect(${option.id})`)} - lineStyle={lineStyle} - lineTypes={lists.lineTypes} - lineWeights={lists.lineWeights} - activeLineTypeId={active.lineType} - activeLineWeightId={active.lineWeight} - onLineTypeSelect={type => { add(`onLineTypeSelect(${type.id})`); setActive(current => ({ ...current, lineType: type.id })); setLineStyle(current => ({ ...current, name: type.name })) }} - onLineWeightSelect={weight => { add(`onLineWeightSelect(${weight.id})`); setActive(current => ({ ...current, lineWeight: weight.id })); setLineStyle(current => ({ ...current, weight: weight.value ?? weight.name })) }} - onLineWeightValueChange={(weight, value) => update("lineWeights", list => list.map(item => (item.id === weight.id ? { ...item, value } : item)), `onLineWeightValueChange(${weight.id}, ${value})`)} - onLineScaleChange={value => { add(`onLineScaleChange(${value})`); setLineStyle(current => ({ ...current, scale: value })) }} - textStyles={lists.textStyles} - activeTextStyleId={active.textStyle} - onTextStyleSelect={style => { add(`onTextStyleSelect(${style.id})`); setActive(current => ({ ...current, textStyle: style.id })) }} - dimensionStyles={lists.dimensionStyles} - activeDimensionStyleId={active.dimensionStyle} - onDimensionStyleSelect={style => { add(`onDimensionStyleSelect(${style.id})`); setActive(current => ({ ...current, dimensionStyle: style.id })) }} - /> - - - ) -} - -export const DynamicData: Story = { - name: "Dynamic Data", - parameters: { controls: { disable: true } }, - render: () => ( - - - - - - - ), -} - /* Additional review 2026-10-16: fixture values are host data, never package defaults. */ const PROPERTY_GROUPS: SWHeaderPropertyGroup[] = [ { id: "common", collapsedCount: 6 },