@nice2dev/ui-buildings 1.1.6 → 1.1.7
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/CHANGELOG.md +51 -0
- package/dist/assets/import.worker-DmRf3ygm.js +1 -0
- package/dist/index.cjs +138 -4
- package/dist/index.d.ts +12 -3
- package/dist/index.mjs +5942 -3930
- package/dist/ui-buildings.css +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# @nice2dev/ui-buildings
|
|
2
2
|
|
|
3
|
+
## 1.1.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Close the three items left open in the 1.1.6 response to OmniVerk.
|
|
8
|
+
|
|
9
|
+
**Every value control works without state in the parent.** The `audit-controllable-state` gate
|
|
10
|
+
counted 87 value props that were required with no `default*`, so the control could not render from a
|
|
11
|
+
manifest without data. It now reports 0 and gates CI at `--max=0`. 48 controls gained `default*` props
|
|
12
|
+
through `useControllableState` (existing `value` + handler call sites behave as before); 33 read-only
|
|
13
|
+
data lists are optional with a stable empty default; 4 props paired with a handler only by name are
|
|
14
|
+
optional; `NiceWhiteboard` and `NiceMetricsDashboard` render an empty state until a session or
|
|
15
|
+
dashboard arrives. Additive API only — nothing renamed or removed.
|
|
16
|
+
|
|
17
|
+
- `NicePivotGrid.fields`, `NiceScheduler.events` and `NiceGitHooks.hooks` are controlled only together
|
|
18
|
+
with their change handler, as `NiceScheduler` already documented for `currentDate`/`view`. A bare
|
|
19
|
+
prop stays an initial value; prop plus handler now always wins (later prop updates used to be
|
|
20
|
+
ignored). `NiceGitHooks.onHookChange` is now called; `onHooksChange` and
|
|
21
|
+
`NiceLocaleManager.onTranslationsChange` are new.
|
|
22
|
+
- `NiceCodeEditor` / `NiceCodeDiffEditor` no longer report a value written from the prop back through
|
|
23
|
+
`onChange`, and call the latest handler rather than the one captured at mount.
|
|
24
|
+
- `NiceHtmlEditor` no longer rewrites its content on every render (React 19 compares the
|
|
25
|
+
`dangerouslySetInnerHTML` object, not its string), which moved the caret; the HTML source and
|
|
26
|
+
Markdown views can be closed again.
|
|
27
|
+
- Selections seeded once from the first item (access manager, automation/scene editors, git diff
|
|
28
|
+
viewer, ribbon, setup wizard) follow data that arrives after mount.
|
|
29
|
+
- `useControllableState`: new `fallbackValue` seed that never triggers the value/default clash warning;
|
|
30
|
+
two functional updates in one tick no longer lose the first; `onChange` is called with one argument
|
|
31
|
+
when there is no meta. `UseControllableStateOptions` is now a union type alias.
|
|
32
|
+
|
|
33
|
+
**`--nice-*` is the source of truth for design tokens.** Controls read only `--nice-*` (9,225 reads in
|
|
34
|
+
339 files). The unprefixed names (`--color-primary`, `--bg-primary`, `--text-muted`, …) stay declared
|
|
35
|
+
as aliases pointing at the Nice tokens, so reading them works, but setting them no longer repaints Nice
|
|
36
|
+
controls. Apps that relied on that can import `@nice2dev/ui/css/legacy-bg-text-aliases.css` after
|
|
37
|
+
`style.css` (removed in 1.2), or set `--nice-color-primary` and friends directly. 13 tokens that were
|
|
38
|
+
read and never declared (`--color-danger`, `--text-on-primary`, `--color-white`, …) are defined; the
|
|
39
|
+
dark blocks define the canonical names, so `.nice-dark` on `<body>` no longer leaves them on light
|
|
40
|
+
values; `--nice-primary-bg` and `--nice-selected-bg` are a primary tint instead of falling through to
|
|
41
|
+
grey. New gate `audit-token-names`.
|
|
42
|
+
|
|
43
|
+
**Node ESM and `require()`.** `@nice2dev/spatial-core` imports from plain Node ESM (51 relative
|
|
44
|
+
specifiers gained extensions, enforced by `nodenext`), and so does `@nice2dev/ui-buildings`, which
|
|
45
|
+
failed through it. `require()` works for `ui-3d`, `ui-graphics` and `game-engine`. The package-exports
|
|
46
|
+
gate now loads every entry in both module systems.
|
|
47
|
+
|
|
48
|
+
**Hygiene.** Sources are prettier-formatted and CI gates on it; 640 stale `.d.ts` files were removed
|
|
49
|
+
from source trees (never published).
|
|
50
|
+
|
|
51
|
+
- Updated dependencies
|
|
52
|
+
- @nice2dev/spatial-core@1.1.7
|
|
53
|
+
|
|
3
54
|
## 1.1.6
|
|
4
55
|
|
|
5
56
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){"use strict";function j(c){var m,g;const o=[],s=c.split(/\r?\n/);let t=0,a=!1,e=null,n=[],u=null;for(;t<s.length;){const r=parseInt(((m=s[t])==null?void 0:m.trim())??"",10),d=((g=s[t+1])==null?void 0:g.trim())??"";if(t+=2,r===2&&d==="ENTITIES"){a=!0;continue}if(r===0&&d==="ENDSEC"&&a){e!=null&&e.type&&(n.length>0&&(e.vertices=[...n]),o.push(e)),a=!1;continue}if(a){if(r===0){e!=null&&e.type&&(n.length>0&&(e.vertices=[...n]),o.push(e)),e={type:d,layer:"0"},n=[],u=null;continue}if(e)switch(r){case 8:e.layer=d;break;case 5:e.handle=d;break;case 10:u=parseFloat(d);break;case 20:u!==null&&(n.push({x:u,y:parseFloat(d)}),e.position||(e.position={x:u,y:parseFloat(d)}),u=null);break;case 11:u=parseFloat(d);break;case 21:u!==null&&(n.push({x:u,y:parseFloat(d)}),u=null);break;case 40:(e.type==="CIRCLE"||e.type==="ARC")&&(e.radius=parseFloat(d));break;case 50:e.startAngle=parseFloat(d);break;case 51:e.endAngle=parseFloat(d);break;case 1:e.text=d;break;case 2:e.blockName=d;break;case 70:parseInt(d,10)&1&&(e.closed=!0);break}}}return o}function N(c,o={}){var u,m;const s=Date.now(),t=[],a=[],e=o.scaleFactor??1,n=o.originOffset??{x:0,y:0};try{const g=j(c),r=[],d=[],k=[],S=new Set;let f=0;for(const l of g){if(S.add(l.layer),o.includeLayers&&!o.includeLayers.includes(l.layer)){f++;continue}if((u=o.excludeLayers)!=null&&u.includes(l.layer)){f++;continue}const I=((m=o.layerMappings)==null?void 0:m[l.layer])??l.layer;switch(l.type){case"LINE":if(l.vertices&&l.vertices.length>=2){const h=x(l.vertices[0],e,n),F=x(l.vertices[1],e,n);r.push({start:h,end:F,layer:I})}break;case"LWPOLYLINE":case"POLYLINE":if(l.vertices&&l.vertices.length>=2){const h=l.vertices.map(p=>x(p,e,n));if(l.closed&&o.convertClosedPolylinesToZones){const p=D(h),y=o.minZoneArea??.1;if(p>=y){d.push({name:I,boundary:h,layer:I});continue}}const F=l.closed?h.length:h.length-1;for(let p=0;p<F;p++){const y=h[p],b=h[(p+1)%h.length];r.push({start:y,end:b,layer:I})}}break;case"CIRCLE":if(l.position&&l.radius){const h=x(l.position,e,n);k.push({type:"circle",position:h,layer:I,metadata:{radius:l.radius*e}})}break;case"INSERT":if(l.position&&l.blockName){const h=x(l.position,e,n);k.push({type:"block-reference",position:h,layer:I,metadata:{blockName:l.blockName}})}break;default:f++,t.push({code:"UNSUPPORTED_ENTITY",message:`Unsupported DXF entity type: ${l.type}`,context:{type:l.type,layer:l.layer}})}}return{success:!0,document:P(r,d,k,S,{name:"Imported DXF",sourceFormat:"dxf",units:o.defaultUnits??"metric"}),warnings:t,errors:a,stats:{wallsImported:r.length,zonesImported:d.length,objectsImported:k.length,layersFound:S.size,entitiesSkipped:f,importTimeMs:Date.now()-s}}}catch(g){return a.push({code:"PARSE_ERROR",message:g instanceof Error?g.message:"Unknown error parsing DXF",fatal:!0}),{success:!1,warnings:t,errors:a,stats:{wallsImported:0,zonesImported:0,objectsImported:0,layersFound:0,entitiesSkipped:0,importTimeMs:Date.now()-s}}}}function U(c){const o=[];let s=[],t=0,a=0,e=0,n=0;const u=c.match(/[MmLlHhVvCcSsQqTtAaZz]|[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?/g)??[];let m=0;for(;m<u.length;){const g=u[m];m++;const r=()=>{const d=parseFloat(u[m]??"0");return m++,d};switch(g){case"M":s.length>0&&(o.push(s),s=[]),t=r(),a=r(),e=t,n=a,s.push({x:t,y:a});break;case"m":s.length>0&&(o.push(s),s=[]),t+=r(),a+=r(),e=t,n=a,s.push({x:t,y:a});break;case"L":t=r(),a=r(),s.push({x:t,y:a});break;case"l":t+=r(),a+=r(),s.push({x:t,y:a});break;case"H":t=r(),s.push({x:t,y:a});break;case"h":t+=r(),s.push({x:t,y:a});break;case"V":a=r(),s.push({x:t,y:a});break;case"v":a+=r(),s.push({x:t,y:a});break;case"Z":case"z":s.length>0&&s.push({x:e,y:n}),t=e,a=n;break;case"C":r(),r(),r(),r(),t=r(),a=r(),s.push({x:t,y:a});break;case"c":r(),r(),r(),r(),t+=r(),a+=r(),s.push({x:t,y:a});break;case"Q":r(),r(),t=r(),a=r(),s.push({x:t,y:a});break;case"q":r(),r(),t+=r(),a+=r(),s.push({x:t,y:a});break}}return s.length>0&&o.push(s),o}function $(c){let o=0,s=0,t=1;const a=c.match(/translate\s*\(\s*([-\d.]+)(?:\s*,?\s*([-\d.]+))?\s*\)/);a&&(o=parseFloat(a[1]),s=parseFloat(a[2]??"0"));const e=c.match(/scale\s*\(\s*([-\d.]+)(?:\s*,?\s*([-\d.]+))?\s*\)/);return e&&(t=parseFloat(e[1])),{translate:{x:o,y:s},scale:t}}function z(c,o={}){const s=Date.now(),t=[],a=[],e=o.scaleFactor??1,n=o.originOffset??{x:0,y:0};try{const u=[],m=[],g=[],r=new Set,d=/<path[^>]*\bd="([^"]+)"[^>]*>/gi;let k;for(;(k=d.exec(c))!==null;){const p=k[1],y=k[0],b=y.match(/\bid="([^"]+)"/),w=(b==null?void 0:b[1])??"default";r.add(w);const E=y.match(/\btransform="([^"]+)"/),C=E?$(E[1]):{translate:{x:0,y:0},scale:1},W=U(p);for(const v of W){if(v.length<2)continue;const R=v.map(T=>x({x:T.x*C.scale+C.translate.x,y:T.y*C.scale+C.translate.y},e,n));if(Math.abs(R[0].x-R[R.length-1].x)<.1&&Math.abs(R[0].y-R[R.length-1].y)<.1&&o.convertClosedPolylinesToZones&&D(R)>=(o.minZoneArea??.1)){m.push({name:w,boundary:R,layer:w});continue}for(let T=0;T<R.length-1;T++)u.push({start:R[T],end:R[T+1],layer:w})}}const S=/<line[^>]*\bx1="([^"]+)"[^>]*\by1="([^"]+)"[^>]*\bx2="([^"]+)"[^>]*\by2="([^"]+)"[^>]*>/gi;let f;for(;(f=S.exec(c))!==null;){const p=parseFloat(f[1]),y=parseFloat(f[2]),b=parseFloat(f[3]),w=parseFloat(f[4]),E=x({x:p,y},e,n),C=x({x:b,y:w},e,n);u.push({start:E,end:C,layer:"default"}),r.add("default")}const i=/<rect[^>]*\bx="([^"]+)"[^>]*\by="([^"]+)"[^>]*\bwidth="([^"]+)"[^>]*\bheight="([^"]+)"[^>]*>/gi;let l;for(;(l=i.exec(c))!==null;){const p=parseFloat(l[1]),y=parseFloat(l[2]),b=parseFloat(l[3]),w=parseFloat(l[4]),E=[x({x:p,y},e,n),x({x:p+b,y},e,n),x({x:p+b,y:y+w},e,n),x({x:p,y:y+w},e,n)];o.convertClosedPolylinesToZones?m.push({name:"rect",boundary:E,layer:"default"}):(u.push({start:E[0],end:E[1],layer:"default"}),u.push({start:E[1],end:E[2],layer:"default"}),u.push({start:E[2],end:E[3],layer:"default"}),u.push({start:E[3],end:E[0],layer:"default"})),r.add("default")}const I=/<circle[^>]*\bcx="([^"]+)"[^>]*\bcy="([^"]+)"[^>]*\br="([^"]+)"[^>]*>/gi;let h;for(;(h=I.exec(c))!==null;){const p=parseFloat(h[1]),y=parseFloat(h[2]),b=parseFloat(h[3]),w=x({x:p,y},e,n);g.push({type:"circle",position:w,layer:"default",metadata:{radius:b*e}}),r.add("default")}return{success:!0,document:P(u,m,g,r,{name:"Imported SVG",sourceFormat:"svg",units:o.defaultUnits??"metric"}),warnings:t,errors:a,stats:{wallsImported:u.length,zonesImported:m.length,objectsImported:g.length,layersFound:r.size,entitiesSkipped:0,importTimeMs:Date.now()-s}}}catch(u){return a.push({code:"PARSE_ERROR",message:u instanceof Error?u.message:"Unknown error parsing SVG",fatal:!0}),{success:!1,warnings:t,errors:a,stats:{wallsImported:0,zonesImported:0,objectsImported:0,layersFound:0,entitiesSkipped:0,importTimeMs:Date.now()-s}}}}function _(c,o={}){var u;const s=Date.now(),t=[],a=[],e=o.scaleFactor??1,n=o.originOffset??{x:0,y:0};try{const m=JSON.parse(c),g=[],r=[],d=[],k=new Set;let S=0;const f=m.type==="FeatureCollection"?m.features:[m];for(const l of f){const I=((u=l.properties)==null?void 0:u.layer)??"default";k.add(I);const h=l.geometry;switch(h.type){case"Point":{const F=h.coordinates,p=x({x:F[0],y:F[1]},e,n);d.push({type:"marker",position:p,layer:I,metadata:{properties:l.properties}});break}case"LineString":{const F=h.coordinates;for(let p=0;p<F.length-1;p++){const y=x({x:F[p][0],y:F[p][1]},e,n),b=x({x:F[p+1][0],y:F[p+1][1]},e,n);g.push({start:y,end:b,layer:I})}break}case"MultiLineString":{const F=h.coordinates;for(const p of F)for(let y=0;y<p.length-1;y++){const b=x({x:p[y][0],y:p[y][1]},e,n),w=x({x:p[y+1][0],y:p[y+1][1]},e,n);g.push({start:b,end:w,layer:I})}break}case"Polygon":{const y=h.coordinates[0].map(b=>x({x:b[0],y:b[1]},e,n));r.push({name:I,boundary:y,layer:I});break}case"MultiPolygon":{const F=h.coordinates;for(const p of F){const b=p[0].map(w=>x({x:w[0],y:w[1]},e,n));r.push({name:I,boundary:b,layer:I})}break}default:S++,t.push({code:"UNSUPPORTED_GEOMETRY",message:`Unsupported GeoJSON geometry: ${h.type}`})}}return{success:!0,document:P(g,r,d,k,{name:"Imported GeoJSON",sourceFormat:"geojson",units:o.defaultUnits??"metric"}),warnings:t,errors:a,stats:{wallsImported:g.length,zonesImported:r.length,objectsImported:d.length,layersFound:k.size,entitiesSkipped:S,importTimeMs:Date.now()-s}}}catch(m){return a.push({code:"PARSE_ERROR",message:m instanceof Error?m.message:"Unknown error parsing GeoJSON",fatal:!0}),{success:!1,warnings:t,errors:a,stats:{wallsImported:0,zonesImported:0,objectsImported:0,layersFound:0,entitiesSkipped:0,importTimeMs:Date.now()-s}}}}function X(c,o={}){const s=Date.now(),t=[],a=[];t.push({code:"LIMITED_IFC_SUPPORT",message:"IFC import is limited. For full support, use a dedicated IFC library like web-ifc."});try{const e=[],n=[],u=[],m=new Set;let g=0;const r=c.split(/\r?\n/),d=new Map;for(const S of r){const f=S.match(/^#(\d+)\s*=\s*(\w+)\s*\((.+)\)\s*;?$/);f&&d.set(`#${f[1]}`,{type:f[2],params:f[3]})}for(const[S,f]of d)if(f.type==="IFCWALLSTANDARDCASE"||f.type==="IFCWALL"){m.add("Walls");const i=f.params.match(/'([^']+)'/),l=(i==null?void 0:i[1])??"Wall";t.push({code:"IFC_WALL_SIMPLIFIED",message:`Wall "${l}" (${S}) geometry simplified to placeholder`}),g++}else if(f.type==="IFCSPACE"){m.add("Spaces");const i=f.params.match(/'([^']+)'/),l=(i==null?void 0:i[1])??"Space";t.push({code:"IFC_SPACE_SIMPLIFIED",message:`Space "${l}" (${S}) geometry simplified to placeholder`}),g++}return{success:!0,document:P(e,n,u,m,{name:"Imported IFC",sourceFormat:"ifc",units:o.defaultUnits??"metric"}),warnings:t,errors:a,stats:{wallsImported:e.length,zonesImported:n.length,objectsImported:u.length,layersFound:m.size,entitiesSkipped:g,importTimeMs:Date.now()-s}}}catch(e){return a.push({code:"PARSE_ERROR",message:e instanceof Error?e.message:"Unknown error parsing IFC",fatal:!0}),{success:!1,warnings:t,errors:a,stats:{wallsImported:0,zonesImported:0,objectsImported:0,layersFound:0,entitiesSkipped:0,importTimeMs:Date.now()-s}}}}function G(c,o,s={}){switch(o){case"dxf":return N(c,s);case"svg":return z(c,s);case"geojson":return _(c,s);case"ifc":return X(c,s);default:return{success:!1,warnings:[],errors:[{code:"UNSUPPORTED_FORMAT",message:`Unsupported import format: ${o}`,fatal:!0}],stats:{wallsImported:0,zonesImported:0,objectsImported:0,layersFound:0,entitiesSkipped:0,importTimeMs:0}}}}function M(){return`${Date.now()}-${Math.random().toString(36).slice(2,9)}`}function x(c,o,s){return{x:c.x*o+s.x,y:c.y*o+s.y}}function D(c){let o=0;const s=c.length;for(let t=0;t<s;t++){const a=(t+1)%s;o+=c[t].x*c[a].y,o-=c[a].x*c[t].y}return Math.abs(o/2)}function L(c){if(c.length===0)return{x:0,y:0,width:0,height:0};let o=1/0,s=1/0,t=-1/0,a=-1/0;for(const e of c)e.x<o&&(o=e.x),e.y<s&&(s=e.y),e.x>t&&(t=e.x),e.y>a&&(a=e.y);return{x:o,y:s,width:t-o,height:a-s}}function O(c){let o=0;for(let t=0;t<c.length;t++)o=c.charCodeAt(t)+((o<<5)-o);return`hsl(${Math.abs(o)%360}, 60%, 50%)`}function A(c){return{position:c,rotation:0,scale:{x:1,y:1}}}function P(c,o,s,t,a){const e=new Date().toISOString(),n=`floor-${M()}`,u=[];for(const i of c)u.push(i.start,i.end);for(const i of o)u.push(...i.boundary);for(const i of s)u.push(i.position);const m=L(u),g=c.map(i=>({id:`wall-${M()}`,type:"wall",category:"building",name:"Wall",transform:A(i.start),bounds:L([i.start,i.end]),layer:i.layer,locked:!1,visible:!0,metadata:{end:i.end,thickness:i.thickness??.15,importedAt:e},childIds:[]})),r=s.map(i=>({id:`obj-${M()}`,type:i.type,category:"annotation",name:i.type,transform:A(i.position),bounds:{x:i.position.x-10,y:i.position.y-10,width:20,height:20},layer:i.layer,locked:!1,visible:!0,metadata:{...i.metadata,importedAt:e},childIds:[]})),d=Array.from(t).map(i=>({id:`layer-${M()}`,name:i,type:i.toLowerCase().includes("wall")?"walls":"custom",visible:!0,locked:!1,opacity:1,color:O(i),objects:[...g.filter(l=>l.layer===i),...r.filter(l=>l.layer===i)]})),k={id:n,name:"Imported Floor",level:0,elevation:0,ceilingHeight:2.7,bounds:m,layers:d},S=o.map(i=>({id:`zone-${M()}`,name:i.name,type:"custom",boundary:i.boundary,floorId:n,roomIds:[],color:O(i.name)})),f={$schema:"https://nice2dev.com/schemas/nsp-v1.json",version:"1.0.0",type:"floor-plan",metadata:{id:`doc-${M()}`,name:a.name,description:`Imported from ${a.sourceFormat.toUpperCase()}`,created:e,modified:e,tags:["imported",a.sourceFormat]},floors:[k],settings:{units:a.units,scale:50,grid:{visible:!0,size:.5,snapEnabled:!0},defaultWallHeight:2.7,defaultWallThickness:.15,precision:2}};return f.zones=S,f}self.onmessage=function(c){const{type:o,id:s,content:t,format:a,options:e}=c.data;if(o!=="import"){self.postMessage({type:"error",id:s,error:`Unknown message type: ${o}`});return}try{self.postMessage({type:"progress",id:s,progress:0});const n=G(t,a,e??{});self.postMessage({type:"result",id:s,result:n})}catch(n){self.postMessage({type:"error",id:s,error:n instanceof Error?n.message:"Unknown error in import worker"})}},self.postMessage({type:"ready"})})();
|