@things-factory/board-ai 10.0.0-beta.81 → 10.0.0-beta.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/server/service/styling/effect-tools.d.ts +5 -4
- package/dist-client/server/service/styling/effect-tools.js +12 -4
- package/dist-client/server/service/styling/effect-tools.js.map +1 -1
- package/dist-client/server/service/validation/board-model-schema.d.ts +258 -258
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/styling/effect-tools.d.ts +5 -4
- package/dist-server/service/styling/effect-tools.js +12 -4
- package/dist-server/service/styling/effect-tools.js.map +1 -1
- package/dist-server/service/validation/board-model-schema.d.ts +258 -258
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/server/service/styling/effect-tools.test.ts +18 -0
- package/server/service/styling/effect-tools.ts +14 -6
|
@@ -33,11 +33,12 @@ export interface OpsResult {
|
|
|
33
33
|
errors: string[];
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* setShadow —
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* setShadow — CSS box-shadow / Canvas API 표준 이름 (color/offsetX/offsetY/blur) 그대로
|
|
37
|
+
* state.shadow 에 set. things-scene drawer 는 옛 이름 (left/top/blurSize) 도
|
|
38
|
+
* backwards-compat 으로 읽지만 (effect/shadow.ts:36-47), 새 모델은 canonical 만 사용.
|
|
39
39
|
*
|
|
40
|
-
*
|
|
40
|
+
* synthetic enabled=false → blur 0 + transparent 매핑 (drawer 가 안 그림).
|
|
41
|
+
* 모델에 enabled 필드는 없음.
|
|
41
42
|
*/
|
|
42
43
|
export declare function buildSetShadowOps(input: SetShadowInput): OpsResult;
|
|
43
44
|
export declare function buildSetOpacityOps(input: SetOpacityInput): OpsResult;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { normalizeColor, validateColor } from './color-utils';
|
|
2
2
|
/**
|
|
3
|
-
* setShadow —
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* setShadow — CSS box-shadow / Canvas API 표준 이름 (color/offsetX/offsetY/blur) 그대로
|
|
4
|
+
* state.shadow 에 set. things-scene drawer 는 옛 이름 (left/top/blurSize) 도
|
|
5
|
+
* backwards-compat 으로 읽지만 (effect/shadow.ts:36-47), 새 모델은 canonical 만 사용.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* synthetic enabled=false → blur 0 + transparent 매핑 (drawer 가 안 그림).
|
|
8
|
+
* 모델에 enabled 필드는 없음.
|
|
8
9
|
*/
|
|
9
10
|
export function buildSetShadowOps(input) {
|
|
10
11
|
if (!Array.isArray(input.refids) || input.refids.length === 0) {
|
|
@@ -33,8 +34,15 @@ export function buildSetShadowOps(input) {
|
|
|
33
34
|
if (input.blur !== undefined && (input.blur < 0 || !Number.isFinite(input.blur))) {
|
|
34
35
|
return { ops: [], errors: [`Invalid blur: ${input.blur}`] };
|
|
35
36
|
}
|
|
37
|
+
if (input.offsetX !== undefined && !Number.isFinite(input.offsetX)) {
|
|
38
|
+
return { ops: [], errors: [`Invalid offsetX: ${input.offsetX}`] };
|
|
39
|
+
}
|
|
40
|
+
if (input.offsetY !== undefined && !Number.isFinite(input.offsetY)) {
|
|
41
|
+
return { ops: [], errors: [`Invalid offsetY: ${input.offsetY}`] };
|
|
42
|
+
}
|
|
36
43
|
// CSS / Canvas 표준 canonical 이름 — rename 없음
|
|
37
44
|
const sh = {};
|
|
45
|
+
// validateColor 가 통과한 색만 도달 — normalizeColor 가 여기서 null 반환 안 함
|
|
38
46
|
if (input.color !== undefined)
|
|
39
47
|
sh.color = normalizeColor(input.color);
|
|
40
48
|
if (input.blur !== undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effect-tools.js","sourceRoot":"","sources":["../../../../server/service/styling/effect-tools.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAgC7D
|
|
1
|
+
{"version":3,"file":"effect-tools.js","sourceRoot":"","sources":["../../../../server/service/styling/effect-tools.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * setShadow / setOpacity / setVisible — 효과 / 가시성 / 투명도.\n *\n * setShadow: state.shadow (color/blur/offsetX/offsetY)\n * setOpacity: state.alpha (컴포넌트 전체 알파, 0..1)\n * setVisible: state.hidden 토글 (true → 숨김)\n */\nimport type { BoardEditOp } from '../types'\nimport { normalizeColor, validateColor } from './color-utils'\n\nexport interface SetShadowInput {\n refids: number[]\n /** synthetic — false 면 blur=0 + color=transparent 매핑 (drawer 가 안 그림). 모델에 enabled 필드 없음. */\n enabled?: boolean\n /** state.shadow.color */\n color?: string\n /** Blur radius (CSS box-shadow 의 blur-radius, Canvas 의 shadowBlur). state.shadow.blur. */\n blur?: number\n /** Horizontal offset (CSS box-shadow 의 offset-x, Canvas 의 shadowOffsetX). state.shadow.offsetX. */\n offsetX?: number\n /** Vertical offset (CSS box-shadow 의 offset-y, Canvas 의 shadowOffsetY). state.shadow.offsetY. */\n offsetY?: number\n}\n\nexport interface SetOpacityInput {\n refids: number[]\n /** state.alpha 의 canonical 이름. 0..1. */\n alpha: number\n}\n\nexport interface SetVisibleInput {\n refids: number[]\n visible: boolean\n}\n\nexport interface OpsResult {\n ops: BoardEditOp[]\n errors: string[]\n}\n\n/**\n * setShadow — CSS box-shadow / Canvas API 표준 이름 (color/offsetX/offsetY/blur) 그대로\n * state.shadow 에 set. things-scene drawer 는 옛 이름 (left/top/blurSize) 도\n * backwards-compat 으로 읽지만 (effect/shadow.ts:36-47), 새 모델은 canonical 만 사용.\n *\n * synthetic enabled=false → blur 0 + transparent 매핑 (drawer 가 안 그림).\n * 모델에 enabled 필드는 없음.\n */\nexport function buildSetShadowOps(input: SetShadowInput): OpsResult {\n if (!Array.isArray(input.refids) || input.refids.length === 0) {\n return { ops: [], errors: ['refids must be a non-empty array'] }\n }\n const refids = input.refids.filter(n => typeof n === 'number' && Number.isFinite(n))\n if (refids.length === 0) return { ops: [], errors: ['No valid numeric refids'] }\n\n const noOp =\n input.enabled === undefined &&\n input.color === undefined &&\n input.blur === undefined &&\n input.offsetX === undefined &&\n input.offsetY === undefined\n if (noOp) return { ops: [], errors: ['No shadow changes specified'] }\n\n if (input.enabled === false) {\n // synthetic — false 면 blur 0 + transparent 으로 변환 (drawer 가 안 그림)\n const patch = { shadow: { blur: 0, color: 'transparent' } }\n return { ops: refids.map(refid => ({ op: 'modify', refid, patch })), errors: [] }\n }\n\n if (input.color !== undefined) {\n const v = validateColor(input.color)\n if (!v.valid) return { ops: [], errors: [v.error ?? 'Invalid shadow color'] }\n }\n if (input.blur !== undefined && (input.blur < 0 || !Number.isFinite(input.blur))) {\n return { ops: [], errors: [`Invalid blur: ${input.blur}`] }\n }\n if (input.offsetX !== undefined && !Number.isFinite(input.offsetX)) {\n return { ops: [], errors: [`Invalid offsetX: ${input.offsetX}`] }\n }\n if (input.offsetY !== undefined && !Number.isFinite(input.offsetY)) {\n return { ops: [], errors: [`Invalid offsetY: ${input.offsetY}`] }\n }\n\n // CSS / Canvas 표준 canonical 이름 — rename 없음\n const sh: Record<string, number | string> = {}\n // validateColor 가 통과한 색만 도달 — normalizeColor 가 여기서 null 반환 안 함\n if (input.color !== undefined) sh.color = normalizeColor(input.color)!\n if (input.blur !== undefined) sh.blur = input.blur\n if (input.offsetX !== undefined) sh.offsetX = input.offsetX\n if (input.offsetY !== undefined) sh.offsetY = input.offsetY\n\n const patch = { shadow: sh }\n return { ops: refids.map(refid => ({ op: 'modify', refid, patch })), errors: [] }\n}\n\nexport function buildSetOpacityOps(input: SetOpacityInput): OpsResult {\n if (!Array.isArray(input.refids) || input.refids.length === 0) {\n return { ops: [], errors: ['refids must be a non-empty array'] }\n }\n if (typeof input.alpha !== 'number' || input.alpha < 0 || input.alpha > 1) {\n return { ops: [], errors: [`alpha must be 0..1: ${input.alpha}`] }\n }\n const refids = input.refids.filter(n => typeof n === 'number' && Number.isFinite(n))\n if (refids.length === 0) return { ops: [], errors: ['No valid numeric refids'] }\n\n // canonical 이름 그대로\n const patch = { alpha: input.alpha }\n return { ops: refids.map(refid => ({ op: 'modify', refid, patch })), errors: [] }\n}\n\nexport function buildSetVisibleOps(input: SetVisibleInput): OpsResult {\n if (!Array.isArray(input.refids) || input.refids.length === 0) {\n return { ops: [], errors: ['refids must be a non-empty array'] }\n }\n if (typeof input.visible !== 'boolean') {\n return { ops: [], errors: ['visible must be a boolean'] }\n }\n const refids = input.refids.filter(n => typeof n === 'number' && Number.isFinite(n))\n if (refids.length === 0) return { ops: [], errors: ['No valid numeric refids'] }\n\n // hidden 은 visible 의 inverse\n const patch = { hidden: !input.visible }\n return { ops: refids.map(refid => ({ op: 'modify', refid, patch })), errors: [] }\n}\n"]}
|