@object-ui/plugin-timeline 17.7.0 → 18.0.0
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 +518 -0
- package/README.md +4 -1
- package/dist/ObjectTimeline.d.ts +9 -3
- package/dist/ObjectTimeline.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +231 -227
- package/dist/index.umd.cjs +1 -1
- package/dist/renderHandoff.d.ts +20 -7
- package/dist/renderHandoff.d.ts.map +1 -1
- package/dist/renderer.d.ts.map +1 -1
- package/dist/useTimelineTranslation.d.ts.map +1 -1
- package/package.json +11 -11
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/components"),require("react/jsx-runtime"),require("@object-ui/core"),require("@object-ui/i18n"),require("@object-ui/react"),require("@object-ui/permissions"),require("@object-ui/mobile"),require("zod")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/components`,`react/jsx-runtime`,`@object-ui/core`,`@object-ui/i18n`,`@object-ui/react`,`@object-ui/permissions`,`@object-ui/mobile`,`zod`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginTimeline={},e.React,e.ObjectUIComponents,e.react_jsx_runtime,e.ObjectUICore,e._object_ui_i18n,e.ObjectUIReact,e._object_ui_permissions,e.ObjectUIMobile,e.zod))})(this,function(e,t,n,r,i,a,o,s,c,l){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var u=Object.create,d=Object.defineProperty,f=Object.getOwnPropertyDescriptor,p=Object.getOwnPropertyNames,m=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty,g=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=p(t),a=0,o=i.length,s;a<o;a++)s=i[a],!h.call(e,s)&&s!==n&&d(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=f(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:u(m(e)),g(t||!e||!e.__esModule||!h.call(e,`default`)?d(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var _={"timeline.bucket.overdue":`Overdue`,"timeline.bucket.today":`Today`,"timeline.bucket.tomorrow":`Tomorrow`,"timeline.bucket.thisWeek":`This week`,"timeline.bucket.nextWeek":`Next week`,"timeline.bucket.later":`Later`,"timeline.bucket.noDate":`No date`,"timeline.bucket.unassigned":`Unassigned`,"timeline.scale.week":`Week {{n}}`,"timeline.scale.quarter":`Q{{quarter}} {{year}}`,"timeline.gantt.rowLabel":`Items`,"timeline.gantt.unusableRange.malformedDate":`Unusable gantt date range — {{path}} is {{value}}, which is not a valid date. Every gantt date has to parse: the startDate and endDate on every row item, plus any minDate / maxDate pinned on the schema.`,"timeline.gantt.unusableRange.inverted":`Unusable gantt date range — minDate {{minDate}} is after maxDate {{maxDate}}. A pinned minDate / maxDate overrides the range computed from the rows, so this axis has no columns and no bar can be placed on it; swap the two values.`,"timeline.gantt.unusableRange.malformedRow":`Unusable gantt rows — {{path}} is {{value}}, which is not a row shape. A gantt draws items as a list of rows, every row as an object with a label and its own items, and every row's items as a list of bars; a null, a number, a string or a plain object in any of those places cannot be drawn.`,"timeline.unsupported.objectBoundGantt":`Unsupported variant "gantt" — an object-bound timeline renders the feed variants ({{variants}}). Gantt needs literal rows, each with its own nested items, so the gantt axis (scale) has no effect here.`,"timeline.unconfigured.noDateAxis":`Timeline date axis required — this view declares no date field, and an object-bound timeline will not invent one. Declare one of: {{fields}}. The first is the spec spelling; the rest are legacy aliases.`},v=`timeline.bucket.today`,y=(e,t)=>Object.entries(t??{}).reduce((e,[t,n])=>e.split(`{{${t}}}`).join(String(n)),_[e]||e),ee=(0,a.createSafeTranslation)(_,v),b=new Set([`hour`,`day`,`week`,`month`,`quarter`,`year`]);function te(e){let t=e.scale;return typeof t==`string`&&b.has(t)?t:`month`}function x(e){return typeof e==`string`?(0,i.toDisplayDate)(e):new Date(e)}function S(e){let t=new Date(e);return t.setHours(0,0,0,0),t}var ne=36e5,C={floor:e=>{let t=new Date(e);return t.setMinutes(0,0,0),t},step:e=>{e.setTime(e.getTime()+ne)},label:(e,t,n)=>e.toLocaleString(n,{month:`short`,day:`numeric`,hour:`numeric`})},w={floor:S,step:e=>{e.setDate(e.getDate()+1)},label:(e,t,n)=>e.toLocaleDateString(n,{month:`short`,day:`numeric`})},re={floor:S,step:e=>{e.setDate(e.getDate()+7)},label:(e,t,n,r)=>r(`timeline.scale.week`,{n:t+1})},T={floor:e=>{let t=S(e);return t.setDate(1),t},step:e=>{e.setMonth(e.getMonth()+1)},label:(e,t,n)=>e.toLocaleDateString(n,{month:`short`,year:`numeric`})},ie={floor:e=>{let t=S(e);return t.setMonth(Math.floor(t.getMonth()/3)*3,1),t},step:e=>{e.setMonth(e.getMonth()+3)},label:(e,t,n,r)=>r(`timeline.scale.quarter`,{quarter:Math.floor(e.getMonth()/3)+1,year:e.getFullYear()})},ae={floor:e=>{let t=S(e);return t.setMonth(0,1),t},step:e=>{e.setFullYear(e.getFullYear()+1)},label:e=>String(e.getFullYear())};function E(e){switch(e){case`hour`:return C;case`day`:return w;case`week`:return re;case`quarter`:return ie;case`year`:return ae;default:return T}}function D(e){return typeof e==`string`?(0,i.toDisplayEndDate)(e):x(e)}function O(e,t,n,r,i,a){let o=x(t).getTime(),s=x(n).getTime();if(Number.isNaN(o)||Number.isNaN(s)||o>s)return;let c=a===void 0?s:Math.max(s,a),l=E(e),u=[],d=l.floor(new Date(o));for(;d.getTime()<=c;){let e=d.getTime(),t=l.label(new Date(e),u.length,r,i);l.step(d),u.push({start:e,end:d.getTime(),label:t})}return{start:u[0].start,end:u[u.length-1].end,units:u}}function k(e,t,n){let r=e.end-e.start;return{start:(t-e.start)/r*100,width:(n-t)/r*100}}function oe(e,t,n,r=`en`,i=y){let a=O(e,t,n,r,i);return a?a.units.map(e=>e.label):[]}function A(){let e=(0,i.toDateInputValue)(new Date);return{minDate:e,maxDate:e}}function j(e){if(!Array.isArray(e))return{ok:!1,path:`items`,value:e};let t=[];for(let n=0;n<e.length;n++){let r=e[n];if(typeof r!=`object`||!r||Array.isArray(r))return{ok:!1,path:`items[${n}]`,value:r};let i=r.items;if(i&&!Array.isArray(i))return{ok:!1,path:`items[${n}].items`,value:i};t.push({authored:r,label:r.label,items:i||[]})}return{ok:!0,rows:t}}function M(e){let t=e.flatMap(e=>e.items.flatMap(e=>[e.startDate,e.endDate]));if(t.length===0)return A();let n=Math.min(...t.map(e=>x(e).getTime())),r=Math.max(...t.map(e=>x(e).getTime())),a=Math.max(...e.flatMap(e=>e.items.map(e=>{let t=x(e.startDate).getTime(),n=D(e.endDate).getTime();return n>t?n-1:t})));return{minDate:(0,i.toDateInputValue)(new Date(n)),maxDate:(0,i.toDateInputValue)(new Date(r)),through:a}}var N=e=>{try{return Date.prototype.getTime.call(e),!0}catch{return!1}};function P(e){return typeof e==`string`?JSON.stringify(e):e===void 0?`undefined`:e===null?`null`:typeof e==`symbol`?e.toString():typeof e==`bigint`?`${e}n`:typeof e==`number`||typeof e==`boolean`?String(e):N(e)?Date.prototype.toString.call(e):Array.isArray(e)?`an array`:typeof e==`function`?`a function`:`an object`}var F=e=>typeof e==`string`||typeof e==`number`&&Number.isFinite(e)||N(e);function I(e,t,n){let r=e=>!F(e)||Number.isNaN(x(e).getTime());for(let t=0;t<e.length;t++){let n=e[t].items;for(let e=0;e<n.length;e++)for(let i of[`startDate`,`endDate`]){let a=n[e]?.[i];if(r(a))return{path:`items[${t}].items[${e}].${i}`,value:a}}}for(let[e,i]of[[`minDate`,t],[`maxDate`,n]])if(i&&r(i))return{path:e,value:i}}function L(e,t,n){return k(n,x(e).getTime(),D(t).getTime())}function R(e,t,n){let r=(0,i.toDisplayDate)(e);return t===`short`?r.toLocaleDateString(n):t===`long`?r.toLocaleDateString(n,{year:`numeric`,month:`long`,day:`numeric`}):Number.isNaN(r.getTime())?String(e):(0,i.isRealCalendarDate)(e)?(0,i.toDateInputValue)(r):r.toISOString().split(`T`)[0]}function se({label:e,color:t}){let i=t?{backgroundColor:`${t}22`,color:t,borderColor:`${t}55`}:void 0;return(0,r.jsx)(`span`,{className:(0,n.cn)(`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium`,!t&&`bg-muted text-muted-foreground border-transparent`),style:i,children:e})}function ce(e){let t=[];for(let n of e){let e=n.group==null?``:String(n.group),r=t[t.length-1];r&&r.key===e?r.items.push(n):t.push({key:e,items:[n]})}return t}var z=({schema:e,className:t,style:o,...s})=>{let{variant:c=`vertical`,items:l=[],dateFormat:u=`short`,onItemClick:d}=e,f=(0,a.useDisplayLocale)(),{t:p}=ee();if(c===`vertical`){let e=ce(l),a=e.some(e=>e.key!==``),c=(e,t)=>{let i=e.color?{backgroundColor:`${e.color}33`,borderColor:e.color}:void 0,a=e.time?R(e.time,u,f):e.startDate?R(e.startDate,u,f):``,o=e.endDate&&e.endDate!==e.startDate?R(e.endDate,u,f):``,s=Array.isArray(e.meta)?e.meta:[];return(0,r.jsxs)(G,{density:`compact`,className:(0,n.cn)(e.className,d&&`cursor-pointer`),onClick:()=>d?.(e),children:[(0,r.jsx)(K,{variant:e.color?`default`:e.variant||`default`,style:i,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(q,{children:[(a||o)&&(0,r.jsxs)(Y,{dateTime:e.time||e.startDate,className:`!mb-1 text-xs`,children:[a,o&&(0,r.jsxs)(`span`,{className:`text-muted-foreground/70`,children:[` → `,o]})]}),e.title&&(0,r.jsx)(J,{className:`text-sm sm:text-base mb-1`,children:e.title}),s.length>0&&(0,r.jsx)(`div`,{className:`flex flex-wrap gap-1.5 mt-1 mb-1`,children:s.map(e=>(0,r.jsx)(se,{label:e.label,color:e.color},e.key))}),e.description&&(0,r.jsx)(X,{className:`text-sm text-muted-foreground line-clamp-2 sm:line-clamp-none`,children:e.description}),(0,n.renderChildren)(e.content)]})]},t)};return a?(0,r.jsx)(`div`,{...(0,i.toDomProps)(s),className:(0,n.cn)(`px-4 sm:px-6 py-2`,t),style:o,children:e.map((e,t)=>(0,r.jsxs)(`section`,{className:`mb-4`,children:[(0,r.jsxs)(`header`,{className:`sticky top-0 z-10 -mx-4 sm:-mx-6 px-4 sm:px-6 py-1.5 backdrop-blur bg-background/90 text-xs font-semibold uppercase tracking-wide text-muted-foreground border-b`,children:[(0,r.jsx)(`span`,{children:e.key}),(0,r.jsx)(`span`,{className:`ml-2 text-muted-foreground/60 font-normal normal-case`,children:e.items.length})]}),(0,r.jsx)(U,{className:`mt-3`,children:e.items.map((e,n)=>c(e,`${t}-${n}`))})]},`${e.key}-${t}`))}):(0,r.jsx)(U,{...(0,i.toDomProps)(s),className:t,style:o,children:l.map((e,t)=>c(e,t))})}if(c===`horizontal`)return(0,r.jsx)(he,{...(0,i.toDomProps)(s),className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),style:o,children:l.map((e,t)=>(0,r.jsxs)(ge,{className:(0,n.cn)(e.className,d&&`cursor-pointer`),onClick:()=>d?.(e),children:[(0,r.jsxs)(`div`,{className:`flex flex-col items-center`,children:[(0,r.jsx)(K,{variant:e.variant||`default`,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(`div`,{className:`mt-4 text-center`,children:[e.time&&(0,r.jsx)(Y,{dateTime:e.time,children:R(e.time,u,f)}),e.title&&(0,r.jsx)(J,{children:e.title}),e.description&&(0,r.jsx)(X,{className:`text-center line-clamp-2 sm:line-clamp-none`,children:e.description}),(0,n.renderChildren)(e.content)]})]}),t<l.length-1&&(0,r.jsx)(`div`,{className:`absolute left-full w-16 border-t-2 border-gray-200 top-3`})]},t))});if(c===`gantt`){let a=j(l);if(!a.ok)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unusable-date-range`,role:`alert`,children:p(`timeline.gantt.unusableRange.malformedRow`,{path:a.path,value:P(a.value)})});let c=a.rows,m=I(c,e.minDate,e.maxDate);if(m)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unusable-date-range`,role:`alert`,children:p(`timeline.gantt.unusableRange.malformedDate`,{path:m.path,value:P(m.value)})});let h=M(c),g=e.minDate||h.minDate,_=e.maxDate||h.maxDate,v=O(te(e),g,_,f,p,e.maxDate?void 0:h.through);return v?(0,r.jsxs)(_e,{...(0,i.toDomProps)(s),className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),style:o,children:[(0,r.jsxs)(ve,{children:[(0,r.jsx)(Z,{className:`flex items-center px-2 sm:px-4 py-2 sm:py-3`,children:(0,r.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:e.rowLabel||p(`timeline.gantt.rowLabel`)})}),(0,r.jsx)(Q,{children:(0,r.jsx)(`div`,{className:`flex h-full`,children:v.units.map((e,t)=>(0,r.jsx)(`div`,{className:`shrink-0 min-w-0 overflow-hidden px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center`,style:{width:`${k(v,e.start,e.end).width}%`},children:e.label},t))})})]}),(0,r.jsx)(`div`,{children:(0,r.jsxs)(`div`,{className:`flex`,children:[(0,r.jsx)(Z,{children:c.map((e,t)=>(0,r.jsx)($,{children:(0,r.jsx)(ye,{title:e.label,className:`truncate`,children:e.label})},t))}),(0,r.jsx)(Q,{className:`relative`,children:c.map((e,t)=>(0,r.jsx)($,{className:`relative`,children:e.items.map((n,i)=>{let a=L(n.startDate,n.endDate,v);return(0,r.jsx)(be,{start:a.start,width:a.width,variant:n.variant||`default`,onClick:()=>d?.(n,e.authored,t,i),title:`${n.title||``}\n${R(n.startDate,u,f)} - ${R(n.endDate,u,f)}`,children:(0,r.jsx)(xe,{children:n.title})},i)})},t))})]})})]}):(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unusable-date-range`,role:`alert`,children:p(`timeline.gantt.unusableRange.inverted`,{minDate:P(g),maxDate:P(_)})})}return null};i.ComponentRegistry.register(`timeline`,z,{namespace:`plugin-timeline`,skipFallback:!0,label:`Timeline`,category:`data-display`,inputs:[{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`]},{name:`items`,type:`array`,description:`For vertical/horizontal: Array of { time, title, description, variant, icon, content }. For gantt: Array of { label, items: [{ title, startDate, endDate, variant }] }`},{name:`dateFormat`,type:`enum`,enum:[`short`,`long`,`iso`]},{name:`scale`,type:`enum`,enum:[...b]},{name:`rowLabel`,type:`string`},{name:`minDate`,type:`string`,description:`Override auto-calculated min date (YYYY-MM-DD)`},{name:`maxDate`,type:`string`,description:`Override auto-calculated max date (YYYY-MM-DD)`},{name:`className`,type:`string`}],defaultProps:{variant:`vertical`,dateFormat:`short`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`,icon:`🚀`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`,icon:`🎨`},{time:`2024-03-15`,title:`Beta Release`,description:`Released beta version to testers`,variant:`warning`,icon:`⚡`},{time:`2024-04-01`,title:`Launch`,description:`Official product launch`,variant:`success`,icon:`🎉`}]},examples:{vertical:{variant:`vertical`,dateFormat:`long`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`}]},horizontal:{variant:`horizontal`,dateFormat:`short`,items:[{time:`2024-01-01`,title:`Q1`,description:`First quarter`,variant:`default`},{time:`2024-04-01`,title:`Q2`,description:`Second quarter`,variant:`info`},{time:`2024-07-01`,title:`Q3`,description:`Third quarter`,variant:`warning`},{time:`2024-10-01`,title:`Q4`,description:`Fourth quarter`,variant:`success`}]},gantt:{variant:`gantt`,dateFormat:`short`,scale:`month`,rowLabel:`Projects`,items:[{label:`Backend Development`,items:[{title:`API Design`,startDate:`2024-01-01`,endDate:`2024-01-31`,variant:`success`},{title:`Implementation`,startDate:`2024-02-01`,endDate:`2024-03-31`,variant:`info`}]},{label:`Frontend Development`,items:[{title:`UI Design`,startDate:`2024-01-15`,endDate:`2024-02-15`,variant:`warning`},{title:`Component Dev`,startDate:`2024-02-15`,endDate:`2024-04-15`,variant:`default`}]},{label:`Testing`,items:[{title:`QA Phase`,startDate:`2024-03-01`,endDate:`2024-04-30`,variant:`danger`}]}]}}});function B(e){return typeof e==`number`&&Number.isInteger(e)&&e>0}function le(e,t){return B(e)?e:t}function ue(e,t){return e==null||B(e)?null:`[ObjectUI] ObjectTimeline row cap: ${typeof t==`string`&&t?`object-timeline on ${t}`:`object-timeline`} declared limit: ${String(e)}, which is not a positive integer. A row cap must be a positive integer (the spec refuses zero and negative values), so it was ignored and this timeline fell back to its default row cap (100).`}var de=[`vertical`,`horizontal`],fe=[`timeline.startDateField`,`timeline.dateField`,`mapping.date`,`startDateField`,`dateField`],V=l.z.object({title:l.z.string().optional(),date:l.z.string().optional(),description:l.z.string().optional(),variant:l.z.string().optional()}),pe=l.z.object({mapping:V.optional(),objectName:l.z.string().optional(),titleField:l.z.string().optional(),dateField:l.z.string().optional(),startDateField:l.z.string().optional(),endDateField:l.z.string().optional(),descriptionField:l.z.string().optional(),groupByField:l.z.string().optional(),colorField:l.z.string().optional(),scale:l.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).optional()}),H=({schema:e,dataSource:a,className:l,onRowClick:u,onItemClick:d,...f})=>{let[p,m]=(0,t.useState)([]),[h,g]=(0,t.useState)(()=>{let t=Array.isArray(e.items)&&e.items.length>0,n=Array.isArray(f.data)&&f.data.length>0;return!t&&!n&&!!e.objectName}),[_,v]=(0,t.useState)(null),y=(0,t.useRef)(0),[b,te]=(0,t.useState)(0),x=e.timeline;(0,t.useEffect)(()=>{let t=pe.safeParse(e);t.success||console.warn(`[ObjectTimeline] Invalid timeline configuration:`,t.error.format())},[e]),(0,t.useEffect)(()=>{let t=ue(e.limit,e.objectName);t&&console.warn(t)},[e.limit,e.objectName]);let S=(0,o.useDataScope)(e.bind),{ready:ne,def:C}=(0,o.useSettledSchema)(e.objectName??``,a),w=(0,s.usePermissions)(),re=(0,o.useFilterScope)(),T=(0,o.useResolvedFilter)(e.filter,re),ie=JSON.stringify(T??null),ae=JSON.stringify(e.sort??null),E=!!e.objectName&&!S&&!e.items&&!f.data,D=(0,o.useDataInvalidation)(E?e.objectName:void 0);(0,t.useEffect)(()=>{let t=++y.current,n=()=>y.current===t,r=async()=>{if(!a||typeof a.find!=`function`||!e.objectName){g(!1);return}g(!0);try{let t=(0,i.buildExpandFields)(C?.fields),r=w?.isLoaded?t.filter(t=>w.checkField(e.objectName,t,`read`)):t,o=await a.find(e.objectName,{$filter:T,$orderby:(0,i.convertSortToQueryParams)(e.sort),$top:le(e.limit,100),...r.length>0?{$expand:r}:{}}),s=(0,i.extractRecords)(o);n()&&(m(s),v(null))}catch(e){console.error(e),n()&&v(e)}finally{n()&&g(!1)}};if(E){if(!ne)return;r()}else g(!1)},[e.objectName,a,S,e.items,f.data,b,ne,C,ie,ae,e.limit,w,D]);let O=f.data||S||p,{t:k}=ee(),{fieldOptionLabel:oe}=(0,o.useSafeFieldLabel)(),A=x?.titleField??e.mapping?.title??e.titleField??`name`,j=x?.startDateField??x?.dateField??e.mapping?.date??e.startDateField??e.dateField,M=x?.endDateField??e.endDateField??j,N=e.mapping?.description??e.descriptionField??`description`,P=e.mapping?.variant??`variant`,F=x?.groupByField??e.groupByField,I=x?.colorField??e.colorField,L=(0,t.useMemo)(()=>{if(e.items)return e.items;if(!O||!Array.isArray(O)||!j)return[];let t=j,n=M??j,r=C?.fields??{},a=e.objectName||``,o=e=>{if(!e||!r[e]?.options)return{};let t={};for(let n of r[e].options)n&&n.value!=null&&(t[String(n.value)]=n);return t},s=[`status`,`priority`].filter(e=>r[e]),c={};for(let e of s)c[e]=o(e);let l=(0,i.createFieldColorResolver)(r[I??``]),u=(e,t,n)=>{if(t==null||t===``)return null;let r=n[String(t)];return{label:r?.label?oe(a,e,String(t),r.label):String(t),color:r?.color}},d=O.map(e=>{let r=e[t],o=e[n],d=I?e[I]:void 0,f=F?e[F]:void 0,p=[];if(a)for(let t of s){let n=u(t,e[t],c[t]||{});n&&p.push({key:t,label:n.label,color:n.color})}return{title:(0,i.recordDisplayValueAt)(e,A),time:r,startDate:r,endDate:o,description:(0,i.recordDisplayValueAt)(e,N),variant:e[P]||`default`,color:l(d),group:f,meta:p,_data:e}}),f=e=>{if(!e)return 1/0;let t=(0,i.toDisplayDate)(e).getTime();return Number.isNaN(t)?1/0:t};d.sort((e,t)=>f(e.startDate)-f(t.startDate));let p=new Date,m=e=>new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime(),h=m(p),g=864e5,_=h-(p.getDay()+6)%7*g+7*g,v=_+7*g,y=e=>{if(!e)return k(`timeline.bucket.noDate`);let t=m((0,i.toDisplayDate)(e));return Number.isNaN(t)?k(`timeline.bucket.noDate`):t<h?k(`timeline.bucket.overdue`):t===h?k(`timeline.bucket.today`):t===h+g?k(`timeline.bucket.tomorrow`):k(t<_?`timeline.bucket.thisWeek`:t<v?`timeline.bucket.nextWeek`:`timeline.bucket.later`)};if(F&&!d.every(e=>e.group==null||e.group===``)){let e=o(F);return d.map(t=>{let n=u(F,t.group,e);return{...t,group:n?n.label:t.group!=null&&t.group!==``?String(t.group):k(`timeline.bucket.unassigned`)}})}return d.map(e=>({...e,group:y(e.startDate)}))},[e.items,O,C,e.objectName,A,j,M,N,P,I,F,k,oe]),R=(0,t.useCallback)(async()=>{te(e=>e+1)},[]),{ref:se,isRefreshing:ce,pullDistance:B}=(0,c.usePullToRefresh)({onRefresh:R,enabled:!!e.objectName&&!!a}),V=(0,o.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:u??d}),H=x?.scale??e.scale,U=!!e.items;if(!U&&e.variant===`gantt`)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unsupported-variant`,role:`alert`,children:k(`timeline.unsupported.objectBoundGantt`,{variants:de.join(`, `)})});if(!U&&!j)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-missing-date-axis`,role:`alert`,children:k(`timeline.unconfigured.noDateAxis`,{fields:fe.join(`, `)})});let W={...e,items:L||[],className:l||e.className,...H?{scale:H}:{},onItemClick:e=>{let t=e._data||e;V.handleClick(t),d?.(t)}};return _?(0,r.jsxs)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-error`,role:`alert`,children:[`Error loading timeline: `,_.message]}):h&&(!L||L.length===0)?(0,r.jsxs)(`div`,{className:`flex flex-col h-full min-h-[200px] p-4 gap-3`,"data-testid":`timeline-loading`,role:`status`,"aria-live":`polite`,"aria-busy":`true`,children:[(0,r.jsx)(`span`,{className:`sr-only`,children:`Loading timeline…`}),[0,1,2,3].map(e=>(0,r.jsxs)(`div`,{className:`flex items-start gap-3`,style:{opacity:Math.max(.3,1-e*.18)},children:[(0,r.jsx)(`div`,{className:`h-3 w-3 rounded-full bg-muted/70 animate-pulse mt-1.5 shrink-0`}),(0,r.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,r.jsx)(`div`,{className:`h-4 w-1/3 rounded bg-muted/70 animate-pulse`}),(0,r.jsx)(`div`,{className:`h-3 w-2/3 rounded bg-muted/50 animate-pulse`})]})]},e))]}):(0,r.jsxs)(`div`,{ref:se,className:`relative overflow-auto h-full min-w-0`,"data-testid":`timeline-canvas`,children:[B>0&&(0,r.jsx)(`div`,{className:`flex items-center justify-center text-xs text-muted-foreground`,style:{height:B},children:ce?`Refreshing…`:`Pull to refresh`}),(0,r.jsx)(z,{schema:W}),V.isOverlay&&(0,r.jsx)(n.NavigationOverlay,{...V,title:`Timeline Item`,children:e=>(0,r.jsx)(`div`,{className:`space-y-3`,children:Object.entries(e).map(([e,t])=>(0,r.jsxs)(`div`,{className:`flex flex-col`,children:[(0,r.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:e.replace(/_/g,` `)}),(0,r.jsx)(`span`,{className:`text-sm`,children:String(t??`—`)})]},e))})})]})},U=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`ol`,{ref:i,className:(0,n.cn)(`relative ml-3 border-l border-gray-200`,e),...t}));U.displayName=`Timeline`;var W=(0,n.cva)(`ml-6`,{variants:{density:{default:`mb-10`,compact:`mb-3`,comfortable:`mb-6`}},defaultVariants:{density:`default`}}),G=t.forwardRef(({className:e,density:t,...i},a)=>(0,r.jsx)(`li`,{ref:a,className:(0,n.cn)(W({density:t}),e),...i}));G.displayName=`TimelineItem`;var me=(0,n.cva)(`absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center justify-center`,{variants:{variant:{default:`bg-blue-200 border-blue-400`,success:`bg-emerald-200 border-emerald-500`,warning:`bg-amber-200 border-amber-500`,danger:`bg-red-200 border-red-500`,info:`bg-purple-200 border-purple-500`,todo:`bg-slate-200 border-slate-400`,"in-progress":`bg-blue-200 border-blue-500`,done:`bg-emerald-200 border-emerald-500`}},defaultVariants:{variant:`default`}}),K=t.forwardRef(({className:e,variant:t=`default`,...i},a)=>(0,r.jsx)(`div`,{ref:a,className:(0,n.cn)(me({variant:t}),e),...i}));K.displayName=`TimelineMarker`;var q=t.forwardRef(({className:e,...t},n)=>(0,r.jsx)(`div`,{ref:n,className:e,...t}));q.displayName=`TimelineContent`;var J=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`h3`,{ref:i,className:(0,n.cn)(`font-semibold text-lg mb-1`,e),...t}));J.displayName=`TimelineTitle`;var Y=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`time`,{ref:i,className:(0,n.cn)(`text-sm font-normal text-gray-500 mb-2 block`,e),...t}));Y.displayName=`TimelineTime`;var X=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`p`,{ref:i,className:(0,n.cn)(`text-base text-gray-700`,e),...t}));X.displayName=`TimelineDescription`;var he=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative flex overflow-x-auto py-8`,e),...t}));he.displayName=`TimelineHorizontal`;var ge=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`shrink-0 w-64 relative`,e),...t}));ge.displayName=`TimelineHorizontalItem`;var _e=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative w-full border rounded-lg overflow-hidden`,e),...t}));_e.displayName=`TimelineGantt`;var ve=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex border-b bg-gray-50`,e),...t}));ve.displayName=`TimelineGanttHeader`;var Z=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`w-48 border-r bg-white`,e),...t}));Z.displayName=`TimelineGanttRowLabels`;var Q=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex-1 overflow-x-auto`,e),...t}));Q.displayName=`TimelineGanttGrid`;var $=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex items-center border-b min-h-12`,e),...t}));$.displayName=`TimelineGanttRow`;var ye=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-4 py-2 font-medium text-sm truncate`,e),...t}));ye.displayName=`TimelineGanttLabel`;var be=t.forwardRef(({className:e,start:t=0,width:i=100,variant:a=`default`,...o},s)=>(0,r.jsx)(`div`,{ref:s,className:(0,n.cn)(`absolute h-8 rounded-md transition-colors cursor-pointer`,{default:`bg-blue-500 hover:bg-blue-600`,success:`bg-green-500 hover:bg-green-600`,warning:`bg-yellow-500 hover:bg-yellow-600`,danger:`bg-red-500 hover:bg-red-600`,info:`bg-purple-500 hover:bg-purple-600`}[a],e),style:{left:`${t}%`,width:`${i}%`},...o}));be.displayName=`TimelineGanttBar`;var xe=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-2 py-1 text-white text-xs font-medium truncate`,e),...t}));xe.displayName=`TimelineGanttBarContent`;var Se={filter:!0,sort:!0,limit:`limit`},Ce=(0,i.elementDataSourceBlock)(({schema:e,...t})=>{let{dataSource:n}=(0,o.useSchemaContext)()||{};return(0,r.jsx)(o.ElementDataSourceGate,{schema:e,mapping:Se,dataSource:n,testId:`object-timeline`,errorTitle:`This timeline’s data source could not be resolved`,children:e=>(0,r.jsx)(H,{schema:e,dataSource:n,...t})})}),we=[{name:`objectName`,type:`string`,description:"Object this timeline binds to. Optional because the component-level `dataSource` binding can supply the object instead — this block registers through `ElementDataSourceGate`, which lowers the binding onto this key before the renderer sees the node. A timeline drawn from `items`, `data` or a `bind` path issues no query and needs none to draw, but `navigation` still reads it: without it `page` opens nothing and `new_window` / `openNewTab` open no record page."},{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`]},{name:`filter`,type:`array`,description:"Base query filter in the rule-array form `[{ field, operator, value }, ...]`, narrowing the records the timeline fetches. Context tokens such as `{current_user_id}` are resolved first, then the filter is lowered to `$filter` on the query. Authored `items` or `data` suppress that query, so the key then narrows nothing. The MongoDB-style record form is not this key’s shape."},{name:`sort`,type:`array`,description:"Order of the records the timeline fetches, in `[{ field, order }]` form, lowered to `$orderby` on the same query. The rail draws entries composed from records by their start date, earliest first, whatever this order. Authored `items` or `data` suppress the query, so the key then orders nothing."},{name:`navigation`,type:`object`,description:"What an entry click opens — the `{ mode, size, openNewTab, preventNavigation }` block a list view declares. With the key ABSENT a click opens nothing: this renderer supplies no drawer default. `mode` is an overlay (`drawer`, `modal`, `split`, `popover`), `new_window`, `page` or `none`, and a block written without `mode` takes the spec’s `page` default. `drawer`, `modal` and `popover` open the entry’s record in that overlay, but `split` opens nothing, because the timeline hands the split shell no main panel; `new_window` opens the record page in a new tab; `none` opens nothing. `page` opens the record page of the timeline’s `objectName` through the record navigator the host publishes (the console publishes one on its custom pages, record pages and list views); under a host that publishes none, such as an embedded renderer, or on a timeline that names no `objectName`, there is no record page to open and the click opens nothing. `preventNavigation: true` opens nothing whatever the mode, `openNewTab: true` opens the record page in a new tab and outranks every mode except `none`, and `size` sets the overlay width. On a timeline that names no `objectName`, `new_window` and `openNewTab` open no record page either: the new tab’s address is a slash and the entry’s `id` alone (its `_id` when it has no `id`, `undefined` when it has neither). A click handler from a parent view outranks the whole key."},{name:`timeline`,type:`object`,description:"Timeline configuration, the author face — the same block `ListViewSchema.timeline` declares: { startDateField, endDateField, titleField, groupByField, colorField, scale }. The flat top-level spellings beside it are the runtime handoff, not a second authoring spelling. On entries composed from records, `startDateField` is the entry’s date, `endDateField` the end printed after it, `titleField` the title, `groupByField` the field whose value heads each group (without it, entries group into date buckets), and `colorField` the field whose option colour, or the value itself when it is a colour literal, paints the marker. Each outranks the flat key of the same binding, and `titleField` / `startDateField` outrank `mapping`’s `title` / `date`. `scale` sets the axis unit of the gantt branch, which on this block draws authored `items` only."},{name:`limit`,type:`number`,description:"Maximum number of records loaded onto the rail (row cap); lowered to the query's top-level `$top` (renderer default 100). A timeline renders one rail with no pagination control, so this is the author's window rather than a page size. A value that is not a positive integer is ignored with a console warning, and the default cap applies."},{name:`data`,type:`array`,description:"Pre-fetched records — read FIRST as the rail's row source, ahead of the data-scope binding and the fetch, and composed into entries through the same `timeline` field bindings a fetched row takes; authoring it suppresses the object query entirely. Distinct from `items`, which is the already-composed entry shape and wins over this key when both are written."},{name:`items`,type:`array`,description:"Static inline entries — read ahead of every record source, `data` above included, and bypasses the object query entirely (the renderer becomes a pass-through). Each element is objectui's declared timeline element, `@object-ui/types`'s `TimelineFeedItem` (`variant` absent / `vertical` / `horizontal`) or `TimelineGanttItem` (`variant: 'gantt'`), the arm this node's `variant` selects. They are drawn as written: the `timeline` block’s field bindings, `mapping` and `descriptionField` do not apply to them."},{name:`dateFormat`,type:`enum`,enum:[`short`,`long`,`iso`],description:"How each entry's date is rendered (renderer default `short`): `short` / `long` are locale-formatted, `iso` is the locale-free machine form."},{name:`rowLabel`,type:`string`,description:"Header label for the gantt row column — read by the gantt branch only, which on this block needs authored `items`. Without it the header shows the default label."},{name:`minDate`,type:`string`,description:"Pin the gantt axis start (ISO `yyyy-mm-dd`) instead of deriving it from the rows; only a non-empty value is honoured. A value that is not a date, or a `minDate` after `maxDate`, refuses the chart with a diagnostic naming it."},{name:`maxDate`,type:`string`,description:"Pin the gantt axis end (ISO `yyyy-mm-dd`) instead of deriving it from the rows; only a non-empty value is honoured. A value that is not a date, or a `maxDate` before `minDate`, refuses the chart with a diagnostic naming it."},{name:`descriptionField`,type:`string`,description:"Field rendered as each entry's description (renderer default `description`). It is declared flat because the `timeline` block has no member for it, and `mapping.description` outranks it when both are written."},{name:`mapping`,type:`object`,description:"Record-to-entry field mapping ({ title, date, description, variant }) — the objectui-side binding record read BETWEEN the `timeline` block and the flat fallbacks. Its `variant` member (the field whose value picks each marker colour, renderer default `variant`) is the only spelling that binding has. On the vertical rail a colour that `timeline.colorField` resolves for an entry outranks that marker colour."}];i.ComponentRegistry.register(`object-timeline`,Ce,{namespace:`plugin-timeline`,label:`Object Timeline`,category:`view`,inputs:[...we]}),i.ComponentRegistry.register(`timeline`,Ce,{namespace:`view`,label:`Timeline View`,category:`view`,inputs:[...we]}),e.ObjectTimeline=H,e.ObjectTimelineRenderer=Ce,e.TIMELINE_SCALES=b,e.Timeline=U,e.TimelineContent=q,e.TimelineDescription=X,e.TimelineGantt=_e,e.TimelineGanttBar=be,e.TimelineGanttBarContent=xe,e.TimelineGanttGrid=Q,e.TimelineGanttHeader=ve,e.TimelineGanttLabel=ye,e.TimelineGanttRow=$,e.TimelineGanttRowLabels=Z,e.TimelineHorizontal=he,e.TimelineHorizontalItem=ge,e.TimelineItem=G,e.TimelineMarker=K,e.TimelineRenderer=z,e.TimelineTime=Y,e.TimelineTitle=J,e.generateTimeScaleHeaders=oe,e.resolveTimelineScale=te,e.timelineItemVariants=W,e.timelineMarkerVariants=me});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/components"),require("react/jsx-runtime"),require("@object-ui/core"),require("@object-ui/i18n"),require("@object-ui/react"),require("@object-ui/permissions"),require("@object-ui/mobile"),require("zod")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/components`,`react/jsx-runtime`,`@object-ui/core`,`@object-ui/i18n`,`@object-ui/react`,`@object-ui/permissions`,`@object-ui/mobile`,`zod`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginTimeline={},e.React,e.ObjectUIComponents,e.react_jsx_runtime,e.ObjectUICore,e._object_ui_i18n,e.ObjectUIReact,e._object_ui_permissions,e.ObjectUIMobile,e.zod))})(this,function(e,t,n,r,i,a,o,s,c,l){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var u=Object.create,d=Object.defineProperty,f=Object.getOwnPropertyDescriptor,p=Object.getOwnPropertyNames,m=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty,g=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=p(t),a=0,o=i.length,s;a<o;a++)s=i[a],!h.call(e,s)&&s!==n&&d(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=f(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:u(m(e)),g(t||!e||!e.__esModule||!h.call(e,`default`)?d(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var _={"timeline.bucket.earlier":`Earlier`,"timeline.bucket.today":`Today`,"timeline.bucket.tomorrow":`Tomorrow`,"timeline.bucket.thisWeek":`This week`,"timeline.bucket.nextWeek":`Next week`,"timeline.bucket.later":`Later`,"timeline.bucket.noDate":`No date`,"timeline.bucket.unassigned":`Unassigned`,"timeline.scale.week":`Week {{n}}`,"timeline.scale.quarter":`Q{{quarter}} {{year}}`,"timeline.gantt.rowLabel":`Items`,"timeline.gantt.unusableRange.malformedDate":`Unusable gantt date range — {{path}} is {{value}}, which is not a valid date. Every gantt date has to parse: the startDate and endDate on every row item, plus any minDate / maxDate pinned on the schema.`,"timeline.gantt.unusableRange.inverted":`Unusable gantt date range — minDate {{minDate}} is after maxDate {{maxDate}}. A pinned minDate / maxDate overrides the range computed from the rows, so this axis has no columns and no bar can be placed on it; swap the two values.`,"timeline.gantt.unusableRange.malformedRow":`Unusable gantt rows — {{path}} is {{value}}, which is not a row shape. A gantt draws items as a list of rows, every row as an object with a label and its own items, and every row's items as a list of bars; a null, a number, a string or a plain object in any of those places cannot be drawn.`,"timeline.unsupported.objectBoundGantt":`Unsupported variant "gantt" — an object-bound timeline renders the feed variants ({{variants}}). Gantt needs literal rows, each with its own nested items, so the gantt axis (scale) has no effect here.`,"timeline.unconfigured.noDateAxis":`Timeline date axis required — this view declares no date field, and an object-bound timeline will not invent one. Declare one of: {{fields}}. The first is the spec spelling; the rest are legacy aliases.`},v=`timeline.bucket.today`,y=(e,t)=>Object.entries(t??{}).reduce((e,[t,n])=>e.split(`{{${t}}}`).join(String(n)),_[e]||e),b=(0,a.createSafeTranslation)(_,v),x=new Set([`hour`,`day`,`week`,`month`,`quarter`,`year`]);function S(e){let t=e.scale;return typeof t==`string`&&x.has(t)?t:`month`}function C(e){return typeof e==`string`?(0,i.toDisplayDate)(e):new Date(e)}function w(e){let t=new Date(e);return t.setHours(0,0,0,0),t}var T=36e5,ee={floor:e=>{let t=new Date(e);return t.setMinutes(0,0,0),t},step:e=>{e.setTime(e.getTime()+T)},label:(e,t,n)=>e.toLocaleString(n,{month:`short`,day:`numeric`,hour:`numeric`})},E={floor:w,step:e=>{e.setDate(e.getDate()+1)},label:(e,t,n)=>e.toLocaleDateString(n,{month:`short`,day:`numeric`})},D={floor:w,step:e=>{e.setDate(e.getDate()+7)},label:(e,t,n,r)=>r(`timeline.scale.week`,{n:t+1})},te={floor:e=>{let t=w(e);return t.setDate(1),t},step:e=>{e.setMonth(e.getMonth()+1)},label:(e,t,n)=>e.toLocaleDateString(n,{month:`short`,year:`numeric`})},O={floor:e=>{let t=w(e);return t.setMonth(Math.floor(t.getMonth()/3)*3,1),t},step:e=>{e.setMonth(e.getMonth()+3)},label:(e,t,n,r)=>r(`timeline.scale.quarter`,{quarter:Math.floor(e.getMonth()/3)+1,year:e.getFullYear()})},ne={floor:e=>{let t=w(e);return t.setMonth(0,1),t},step:e=>{e.setFullYear(e.getFullYear()+1)},label:e=>String(e.getFullYear())};function re(e){switch(e){case`hour`:return ee;case`day`:return E;case`week`:return D;case`quarter`:return O;case`year`:return ne;default:return te}}function k(e){return typeof e==`string`?(0,i.toDisplayEndDate)(e):C(e)}function ie(e,t,n,r,i,a){let o=C(t).getTime(),s=C(n).getTime();if(Number.isNaN(o)||Number.isNaN(s)||o>s)return;let c=a===void 0?s:Math.max(s,a),l=re(e),u=[],d=l.floor(new Date(o));for(;d.getTime()<=c;){let e=d.getTime(),t=l.label(new Date(e),u.length,r,i);l.step(d),u.push({start:e,end:d.getTime(),label:t})}return{start:u[0].start,end:u[u.length-1].end,units:u}}function A(e,t,n){let r=e.end-e.start;return{start:(t-e.start)/r*100,width:(n-t)/r*100}}function j(e,t,n,r=`en`,i=y){let a=ie(e,t,n,r,i);return a?a.units.map(e=>e.label):[]}function M(){let e=(0,i.toDateInputValue)(new Date);return{minDate:e,maxDate:e}}function N(e){if(!Array.isArray(e))return{ok:!1,path:`items`,value:e};let t=[];for(let n=0;n<e.length;n++){let r=e[n];if(typeof r!=`object`||!r||Array.isArray(r))return{ok:!1,path:`items[${n}]`,value:r};let i=r.items;if(i&&!Array.isArray(i))return{ok:!1,path:`items[${n}].items`,value:i};t.push({authored:r,label:r.label,items:i||[]})}return{ok:!0,rows:t}}function P(e){let t=e.flatMap(e=>e.items.flatMap(e=>[e.startDate,e.endDate]));if(t.length===0)return M();let n=Math.min(...t.map(e=>C(e).getTime())),r=Math.max(...t.map(e=>C(e).getTime())),a=Math.max(...e.flatMap(e=>e.items.map(e=>{let t=C(e.startDate).getTime(),n=k(e.endDate).getTime();return n>t?n-1:t})));return{minDate:(0,i.toDateInputValue)(new Date(n)),maxDate:(0,i.toDateInputValue)(new Date(r)),through:a}}var F=e=>{try{return Date.prototype.getTime.call(e),!0}catch{return!1}};function I(e){return typeof e==`string`?JSON.stringify(e):e===void 0?`undefined`:e===null?`null`:typeof e==`symbol`?e.toString():typeof e==`bigint`?`${e}n`:typeof e==`number`||typeof e==`boolean`?String(e):F(e)?Date.prototype.toString.call(e):Array.isArray(e)?`an array`:typeof e==`function`?`a function`:`an object`}var ae=e=>typeof e==`string`||typeof e==`number`&&Number.isFinite(e)||F(e);function oe(e,t,n){let r=e=>!ae(e)||Number.isNaN(C(e).getTime());for(let t=0;t<e.length;t++){let n=e[t].items;for(let e=0;e<n.length;e++)for(let i of[`startDate`,`endDate`]){let a=n[e]?.[i];if(r(a))return{path:`items[${t}].items[${e}].${i}`,value:a}}}for(let[e,i]of[[`minDate`,t],[`maxDate`,n]])if(i&&r(i))return{path:e,value:i}}function L(e,t,n){return A(n,C(e).getTime(),k(t).getTime())}function R(e,t,n){let r=(0,i.toDisplayDate)(e);return t===`short`?r.toLocaleDateString(n):t===`long`?r.toLocaleDateString(n,{year:`numeric`,month:`long`,day:`numeric`}):Number.isNaN(r.getTime())?String(e):(0,i.isRealCalendarDate)(e)?(0,i.toDateInputValue)(r):r.toISOString().split(`T`)[0]}function z({label:e,color:t}){let i=t?{backgroundColor:`${t}22`,color:t,borderColor:`${t}55`}:void 0;return(0,r.jsx)(`span`,{className:(0,n.cn)(`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium`,!t&&`bg-muted text-muted-foreground border-transparent`),style:i,children:e})}function se(e){let t=[],n=new Map;for(let r of e){let e=r.group==null?``:String(r.group),i=n.get(e);if(i)i.items.push(r);else{let i={key:e,items:[r]};n.set(e,i),t.push(i)}}return t}var B=({schema:e,className:t,style:o,...s})=>{let{variant:c=`vertical`,items:l=[],dateFormat:u=`short`,onItemClick:d}=e,f=(0,a.useDisplayLocale)(),{t:p}=b();if(c===`vertical`){let e=se(l),a=e.some(e=>e.key!==``),c=(e,t)=>{let i=e.color?{backgroundColor:`${e.color}33`,borderColor:e.color}:void 0,a=e.time?R(e.time,u,f):e.startDate?R(e.startDate,u,f):``,o=e.endDate&&e.endDate!==e.startDate?R(e.endDate,u,f):``,s=Array.isArray(e.meta)?e.meta:[];return(0,r.jsxs)(G,{density:`compact`,className:(0,n.cn)(e.className,d&&`cursor-pointer`),onClick:()=>d?.(e),children:[(0,r.jsx)(K,{variant:e.color?`default`:e.variant||`default`,style:i,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(he,{children:[(a||o)&&(0,r.jsxs)(J,{dateTime:e.time||e.startDate,className:`!mb-1 text-xs`,children:[a,o&&(0,r.jsxs)(`span`,{className:`text-muted-foreground/70`,children:[` → `,o]})]}),e.title&&(0,r.jsx)(q,{className:`text-sm sm:text-base mb-1`,children:e.title}),s.length>0&&(0,r.jsx)(`div`,{className:`flex flex-wrap gap-1.5 mt-1 mb-1`,children:s.map(e=>(0,r.jsx)(z,{label:e.label,color:e.color},e.key))}),e.description&&(0,r.jsx)(Y,{className:`text-sm text-muted-foreground line-clamp-2 sm:line-clamp-none`,children:e.description}),(0,n.renderChildren)(e.content)]})]},t)};return a?(0,r.jsx)(`div`,{...(0,i.toDomProps)(s),className:(0,n.cn)(`px-4 sm:px-6 py-2`,t),style:o,children:e.map((e,t)=>(0,r.jsxs)(`section`,{className:`mb-4`,children:[(0,r.jsxs)(`header`,{className:`sticky top-0 z-10 -mx-4 sm:-mx-6 px-4 sm:px-6 py-1.5 backdrop-blur bg-background/90 text-xs font-semibold uppercase tracking-wide text-muted-foreground border-b`,children:[(0,r.jsx)(`span`,{children:e.key}),(0,r.jsx)(`span`,{className:`ml-2 text-muted-foreground/60 font-normal normal-case`,children:e.items.length})]}),(0,r.jsx)(U,{className:`mt-3`,children:e.items.map((e,n)=>c(e,`${t}-${n}`))})]},`${e.key}-${t}`))}):(0,r.jsx)(U,{...(0,i.toDomProps)(s),className:t,style:o,children:l.map((e,t)=>c(e,t))})}if(c===`horizontal`)return(0,r.jsx)(X,{...(0,i.toDomProps)(s),className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),style:o,children:l.map((e,t)=>(0,r.jsxs)(ge,{className:(0,n.cn)(e.className,d&&`cursor-pointer`),onClick:()=>d?.(e),children:[(0,r.jsxs)(`div`,{className:`flex flex-col items-center`,children:[(0,r.jsx)(K,{variant:e.variant||`default`,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(`div`,{className:`mt-4 text-center`,children:[e.time&&(0,r.jsx)(J,{dateTime:e.time,children:R(e.time,u,f)}),e.title&&(0,r.jsx)(q,{children:e.title}),e.description&&(0,r.jsx)(Y,{className:`text-center line-clamp-2 sm:line-clamp-none`,children:e.description}),(0,n.renderChildren)(e.content)]})]}),t<l.length-1&&(0,r.jsx)(`div`,{className:`absolute left-full w-16 border-t-2 border-gray-200 top-3`})]},t))});if(c===`gantt`){let a=N(l);if(!a.ok)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unusable-date-range`,role:`alert`,children:p(`timeline.gantt.unusableRange.malformedRow`,{path:a.path,value:I(a.value)})});let c=a.rows,m=oe(c,e.minDate,e.maxDate);if(m)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unusable-date-range`,role:`alert`,children:p(`timeline.gantt.unusableRange.malformedDate`,{path:m.path,value:I(m.value)})});let h=P(c),g=e.minDate||h.minDate,_=e.maxDate||h.maxDate,v=ie(S(e),g,_,f,p,e.maxDate?void 0:h.through);return v?(0,r.jsxs)(_e,{...(0,i.toDomProps)(s),className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),style:o,children:[(0,r.jsxs)(ve,{children:[(0,r.jsx)(Z,{className:`flex items-center px-2 sm:px-4 py-2 sm:py-3`,children:(0,r.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:e.rowLabel||p(`timeline.gantt.rowLabel`)})}),(0,r.jsx)(Q,{children:(0,r.jsx)(`div`,{className:`flex h-full`,children:v.units.map((e,t)=>(0,r.jsx)(`div`,{className:`shrink-0 min-w-0 overflow-hidden px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center`,style:{width:`${A(v,e.start,e.end).width}%`},children:e.label},t))})})]}),(0,r.jsx)(`div`,{children:(0,r.jsxs)(`div`,{className:`flex`,children:[(0,r.jsx)(Z,{children:c.map((e,t)=>(0,r.jsx)($,{children:(0,r.jsx)(ye,{title:e.label,className:`truncate`,children:e.label})},t))}),(0,r.jsx)(Q,{className:`relative`,children:c.map((e,t)=>(0,r.jsx)($,{className:`relative`,children:e.items.map((n,i)=>{let a=L(n.startDate,n.endDate,v);return(0,r.jsx)(be,{start:a.start,width:a.width,variant:n.variant||`default`,onClick:()=>d?.(n,e.authored,t,i),title:`${n.title||``}\n${R(n.startDate,u,f)} - ${R(n.endDate,u,f)}`,children:(0,r.jsx)(xe,{children:n.title})},i)})},t))})]})})]}):(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unusable-date-range`,role:`alert`,children:p(`timeline.gantt.unusableRange.inverted`,{minDate:I(g),maxDate:I(_)})})}return null};i.ComponentRegistry.register(`timeline`,B,{namespace:`plugin-timeline`,skipFallback:!0,label:`Timeline`,category:`data-display`,inputs:[{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`]},{name:`items`,type:`array`,description:`For vertical/horizontal: Array of { time, title, description, variant, icon, content }. For gantt: Array of { label, items: [{ title, startDate, endDate, variant }] }`},{name:`dateFormat`,type:`enum`,enum:[`short`,`long`,`iso`]},{name:`scale`,type:`enum`,enum:[...x]},{name:`rowLabel`,type:`string`},{name:`minDate`,type:`string`,description:`Override auto-calculated min date (YYYY-MM-DD)`},{name:`maxDate`,type:`string`,description:`Override auto-calculated max date (YYYY-MM-DD)`},{name:`className`,type:`string`}],defaultProps:{variant:`vertical`,dateFormat:`short`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`,icon:`🚀`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`,icon:`🎨`},{time:`2024-03-15`,title:`Beta Release`,description:`Released beta version to testers`,variant:`warning`,icon:`⚡`},{time:`2024-04-01`,title:`Launch`,description:`Official product launch`,variant:`success`,icon:`🎉`}]},examples:{vertical:{variant:`vertical`,dateFormat:`long`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`}]},horizontal:{variant:`horizontal`,dateFormat:`short`,items:[{time:`2024-01-01`,title:`Q1`,description:`First quarter`,variant:`default`},{time:`2024-04-01`,title:`Q2`,description:`Second quarter`,variant:`info`},{time:`2024-07-01`,title:`Q3`,description:`Third quarter`,variant:`warning`},{time:`2024-10-01`,title:`Q4`,description:`Fourth quarter`,variant:`success`}]},gantt:{variant:`gantt`,dateFormat:`short`,scale:`month`,rowLabel:`Projects`,items:[{label:`Backend Development`,items:[{title:`API Design`,startDate:`2024-01-01`,endDate:`2024-01-31`,variant:`success`},{title:`Implementation`,startDate:`2024-02-01`,endDate:`2024-03-31`,variant:`info`}]},{label:`Frontend Development`,items:[{title:`UI Design`,startDate:`2024-01-15`,endDate:`2024-02-15`,variant:`warning`},{title:`Component Dev`,startDate:`2024-02-15`,endDate:`2024-04-15`,variant:`default`}]},{label:`Testing`,items:[{title:`QA Phase`,startDate:`2024-03-01`,endDate:`2024-04-30`,variant:`danger`}]}]}}});function V(e){return typeof e==`number`&&Number.isInteger(e)&&e>0}function ce(e,t){return V(e)?e:t}function le(e,t){return e==null||V(e)?null:`[ObjectUI] ObjectTimeline row cap: ${typeof t==`string`&&t?`object-timeline on ${t}`:`object-timeline`} declared limit: ${String(e)}, which is not a positive integer. A row cap must be a positive integer (the spec refuses zero and negative values), so it was ignored and this timeline fell back to its default row cap (100).`}var ue=[`vertical`,`horizontal`],de=[`timeline.startDateField`,`mapping.date`,`startDateField`,`dateField`],fe=l.z.object({title:l.z.string().optional(),date:l.z.string().optional(),description:l.z.string().optional(),variant:l.z.string().optional()}),pe=l.z.object({mapping:fe.optional(),objectName:l.z.string().optional(),titleField:l.z.string().optional(),dateField:l.z.string().optional(),startDateField:l.z.string().optional(),endDateField:l.z.string().optional(),descriptionField:l.z.string().optional(),groupByField:l.z.string().optional(),colorField:l.z.string().optional(),scale:l.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).optional()}),H=({schema:e,dataSource:l,className:u,onRowClick:d,onItemClick:f,...p})=>{let[m,h]=(0,t.useState)([]),[g,_]=(0,t.useState)(()=>{let t=Array.isArray(e.items)&&e.items.length>0,n=Array.isArray(p.data)&&p.data.length>0;return!t&&!n&&!!e.objectName}),[v,y]=(0,t.useState)(null),x=(0,t.useRef)(0),[S,C]=(0,t.useState)(0),w=e.timeline;(0,t.useEffect)(()=>{let t=pe.safeParse(e);t.success||console.warn(`[ObjectTimeline] Invalid timeline configuration:`,t.error.format())},[e]),(0,t.useEffect)(()=>{let t=le(e.limit,e.objectName);t&&console.warn(t)},[e.limit,e.objectName]);let T=(0,o.useDataScope)(e.bind),{ready:ee,def:E}=(0,o.useSettledSchema)(e.objectName??``,l),D=(0,s.usePermissions)(),te=(0,o.useFilterScope)(),O=(0,o.useResolvedFilter)(e.filter,te),ne=JSON.stringify(O??null),re=JSON.stringify(e.sort??null),k=!!e.objectName&&!T&&!e.items&&!p.data,ie=(0,o.useDataInvalidation)(k?e.objectName:void 0);(0,t.useEffect)(()=>{let t=++x.current,n=()=>x.current===t,r=async()=>{if(!l||typeof l.find!=`function`||!e.objectName){_(!1);return}_(!0);try{let t=(0,i.buildExpandFields)(E?.fields),r=D?.isLoaded?t.filter(t=>D.checkField(e.objectName,t,`read`)):t,a=await l.find(e.objectName,{$filter:O,$orderby:(0,i.convertSortToQueryParams)(e.sort),$top:ce(e.limit,100),...r.length>0?{$expand:r}:{}}),o=(0,i.extractRecords)(a);n()&&(h(o),y(null))}catch(e){console.error(e),n()&&y(e)}finally{n()&&_(!1)}};if(k){if(!ee)return;r()}else _(!1)},[e.objectName,l,T,e.items,p.data,S,ee,E,ne,re,e.limit,D,ie]);let A=p.data||T||m,{t:j}=b(),{fieldOptionLabel:M}=(0,o.useSafeFieldLabel)(),N=(0,a.useDisplayLocale)(),P=w?.titleField??e.mapping?.title??e.titleField??`name`,F=w?.startDateField??e.mapping?.date??e.startDateField??e.dateField,I=w?.endDateField??e.endDateField??F,ae=e.mapping?.description??e.descriptionField??`description`,oe=e.mapping?.variant??`variant`,L=w?.groupByField??e.groupByField,R=w?.colorField??e.colorField,z=(0,t.useMemo)(()=>{if(e.items)return e.items;if(!A||!Array.isArray(A)||!F)return[];let t=F,n=I??F,r=E?.fields??{},o=e.objectName||``,s=e=>{if(!e||!r[e]?.options)return{};let t={};for(let n of r[e].options)n&&n.value!=null&&(t[String(n.value)]=n);return t},c=[`status`,`priority`].filter(e=>r[e]),l={};for(let e of c)l[e]=s(e);let u=(0,i.createFieldColorResolver)(r[R??``]),d=(e,t,n)=>{if(t==null||t===``)return null;let r=n[String(t)];return{label:r?.label?M(o,e,String(t),r.label):String(t),color:r?.color}},f=A.map(e=>{let r=e[t],a=e[n],s=R?e[R]:void 0,f=L?e[L]:void 0,p=[];if(o)for(let t of c){let n=d(t,e[t],l[t]||{});n&&p.push({key:t,label:n.label,color:n.color})}return{title:(0,i.recordDisplayValueAt)(e,P),time:r,startDate:r,endDate:a,description:(0,i.recordDisplayValueAt)(e,ae),variant:e[oe]||`default`,color:u(s),group:f,meta:p,_data:e}}),p=e=>{if(!e)return 1/0;let t=(0,i.toDisplayDate)(e).getTime();return Number.isNaN(t)?1/0:t};f.sort((e,t)=>p(e.startDate)-p(t.startDate));let m=new Date,h=e=>new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime(),g=e=>new Date(m.getFullYear(),m.getMonth(),m.getDate()+e).getTime(),_=g(0),v=g(1),y=(m.getDay()-(0,a.firstDayOfWeek)(N)+7)%7,b=g(7-y),x=g(14-y),S=e=>{if(!e)return j(`timeline.bucket.noDate`);let t=h((0,i.toDisplayDate)(e));return j(Number.isNaN(t)?`timeline.bucket.noDate`:t<_?`timeline.bucket.earlier`:t===_?`timeline.bucket.today`:t===v?`timeline.bucket.tomorrow`:t<b?`timeline.bucket.thisWeek`:t<x?`timeline.bucket.nextWeek`:`timeline.bucket.later`)};if(L){let e=s(L),t=f.map(t=>{let n=t.group!=null&&t.group!==``?e[String(t.group)]:void 0;return n?.label?M(o,L,String(t.group),n.label):Array.isArray(t.group)?String(t.group):(0,i.recordDisplayValueAt)(t._data,L)});if(t.some(e=>e!==void 0))return f.map((e,n)=>({...e,group:t[n]??j(`timeline.bucket.unassigned`)}))}return f.map(e=>({...e,group:S(e.startDate)}))},[e.items,A,E,e.objectName,P,F,I,ae,oe,R,L,j,M,N]),se=(0,t.useCallback)(async()=>{C(e=>e+1)},[]),{ref:V,isRefreshing:fe,pullDistance:H}=(0,c.usePullToRefresh)({onRefresh:se,enabled:!!e.objectName&&!!l}),U=(0,o.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:d??f}),W=w?.scale??e.scale,G=!!e.items;if(!G&&e.variant===`gantt`)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-unsupported-variant`,role:`alert`,children:j(`timeline.unsupported.objectBoundGantt`,{variants:ue.join(`, `)})});if(!G&&!F)return(0,r.jsx)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-missing-date-axis`,role:`alert`,children:j(`timeline.unconfigured.noDateAxis`,{fields:de.join(`, `)})});let me={...e,items:z||[],className:u||e.className,...W?{scale:W}:{},onItemClick:e=>{let t=e._data||e;U.handleClick(t),f?.(t)}};return v?(0,r.jsxs)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-error`,role:`alert`,children:[`Error loading timeline: `,v.message]}):g&&(!z||z.length===0)?(0,r.jsxs)(`div`,{className:`flex flex-col h-full min-h-[200px] p-4 gap-3`,"data-testid":`timeline-loading`,role:`status`,"aria-live":`polite`,"aria-busy":`true`,children:[(0,r.jsx)(`span`,{className:`sr-only`,children:`Loading timeline…`}),[0,1,2,3].map(e=>(0,r.jsxs)(`div`,{className:`flex items-start gap-3`,style:{opacity:Math.max(.3,1-e*.18)},children:[(0,r.jsx)(`div`,{className:`h-3 w-3 rounded-full bg-muted/70 animate-pulse mt-1.5 shrink-0`}),(0,r.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,r.jsx)(`div`,{className:`h-4 w-1/3 rounded bg-muted/70 animate-pulse`}),(0,r.jsx)(`div`,{className:`h-3 w-2/3 rounded bg-muted/50 animate-pulse`})]})]},e))]}):(0,r.jsxs)(`div`,{ref:V,className:`relative overflow-auto h-full min-w-0`,"data-testid":`timeline-canvas`,children:[H>0&&(0,r.jsx)(`div`,{className:`flex items-center justify-center text-xs text-muted-foreground`,style:{height:H},children:fe?`Refreshing…`:`Pull to refresh`}),(0,r.jsx)(B,{schema:me}),U.isOverlay&&(0,r.jsx)(n.NavigationOverlay,{...U,title:`Timeline Item`,children:e=>(0,r.jsx)(`div`,{className:`space-y-3`,children:Object.entries(e).map(([e,t])=>(0,r.jsxs)(`div`,{className:`flex flex-col`,children:[(0,r.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:e.replace(/_/g,` `)}),(0,r.jsx)(`span`,{className:`text-sm`,children:String(t??`—`)})]},e))})})]})},U=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`ol`,{ref:i,className:(0,n.cn)(`relative ml-3 border-l border-gray-200`,e),...t}));U.displayName=`Timeline`;var W=(0,n.cva)(`ml-6`,{variants:{density:{default:`mb-10`,compact:`mb-3`,comfortable:`mb-6`}},defaultVariants:{density:`default`}}),G=t.forwardRef(({className:e,density:t,...i},a)=>(0,r.jsx)(`li`,{ref:a,className:(0,n.cn)(W({density:t}),e),...i}));G.displayName=`TimelineItem`;var me=(0,n.cva)(`absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center justify-center`,{variants:{variant:{default:`bg-blue-200 border-blue-400`,success:`bg-emerald-200 border-emerald-500`,warning:`bg-amber-200 border-amber-500`,danger:`bg-red-200 border-red-500`,info:`bg-purple-200 border-purple-500`,todo:`bg-slate-200 border-slate-400`,"in-progress":`bg-blue-200 border-blue-500`,done:`bg-emerald-200 border-emerald-500`}},defaultVariants:{variant:`default`}}),K=t.forwardRef(({className:e,variant:t=`default`,...i},a)=>(0,r.jsx)(`div`,{ref:a,className:(0,n.cn)(me({variant:t}),e),...i}));K.displayName=`TimelineMarker`;var he=t.forwardRef(({className:e,...t},n)=>(0,r.jsx)(`div`,{ref:n,className:e,...t}));he.displayName=`TimelineContent`;var q=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`h3`,{ref:i,className:(0,n.cn)(`font-semibold text-lg mb-1`,e),...t}));q.displayName=`TimelineTitle`;var J=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`time`,{ref:i,className:(0,n.cn)(`text-sm font-normal text-gray-500 mb-2 block`,e),...t}));J.displayName=`TimelineTime`;var Y=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`p`,{ref:i,className:(0,n.cn)(`text-base text-gray-700`,e),...t}));Y.displayName=`TimelineDescription`;var X=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative flex overflow-x-auto py-8`,e),...t}));X.displayName=`TimelineHorizontal`;var ge=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`shrink-0 w-64 relative`,e),...t}));ge.displayName=`TimelineHorizontalItem`;var _e=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative w-full border rounded-lg overflow-hidden`,e),...t}));_e.displayName=`TimelineGantt`;var ve=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex border-b bg-gray-50`,e),...t}));ve.displayName=`TimelineGanttHeader`;var Z=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`w-48 border-r bg-white`,e),...t}));Z.displayName=`TimelineGanttRowLabels`;var Q=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex-1 overflow-x-auto`,e),...t}));Q.displayName=`TimelineGanttGrid`;var $=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex items-center border-b min-h-12`,e),...t}));$.displayName=`TimelineGanttRow`;var ye=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-4 py-2 font-medium text-sm truncate`,e),...t}));ye.displayName=`TimelineGanttLabel`;var be=t.forwardRef(({className:e,start:t=0,width:i=100,variant:a=`default`,...o},s)=>(0,r.jsx)(`div`,{ref:s,className:(0,n.cn)(`absolute h-8 rounded-md transition-colors cursor-pointer`,{default:`bg-blue-500 hover:bg-blue-600`,success:`bg-green-500 hover:bg-green-600`,warning:`bg-yellow-500 hover:bg-yellow-600`,danger:`bg-red-500 hover:bg-red-600`,info:`bg-purple-500 hover:bg-purple-600`}[a],e),style:{left:`${t}%`,width:`${i}%`},...o}));be.displayName=`TimelineGanttBar`;var xe=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-2 py-1 text-white text-xs font-medium truncate`,e),...t}));xe.displayName=`TimelineGanttBarContent`;var Se={filter:!0,sort:!0,limit:`limit`},Ce=(0,i.elementDataSourceBlock)(({schema:e,...t})=>{let{dataSource:n}=(0,o.useSchemaContext)()||{},{t:i}=(0,a.useObjectTranslation)();return(0,r.jsx)(o.ElementDataSourceGate,{schema:e,mapping:Se,dataSource:n,testId:`object-timeline`,errorTitle:i(`element.timeline.sourceUnresolved`,{defaultValue:`This timeline’s data source could not be resolved`}),children:e=>(0,r.jsx)(H,{schema:e,dataSource:n,...t})})}),we=[{name:`objectName`,type:`string`,description:"Object this timeline binds to. Optional because the component-level `dataSource` binding can supply the object instead — this block registers through `ElementDataSourceGate`, which lowers the binding onto this key before the renderer sees the node. A timeline drawn from `items`, `data` or a `bind` path issues no query and needs none to draw, but `navigation` still reads it: without it `page` opens nothing and `new_window` / `openNewTab` open no record page."},{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`]},{name:`filter`,type:`array`,description:"Base query filter in the rule-array form `[{ field, operator, value }, ...]`, narrowing the records the timeline fetches. Context tokens such as `{current_user_id}` are resolved first, then the filter is lowered to `$filter` on the query. Authored `items` or `data` suppress that query, so the key then narrows nothing. The MongoDB-style record form is not this key’s shape."},{name:`sort`,type:`array`,description:"Order of the records the timeline fetches, in `[{ field, order }]` form, lowered to `$orderby` on the same query. The rail draws entries composed from records by their start date, earliest first, whatever this order. Authored `items` or `data` suppress the query, so the key then orders nothing."},{name:`navigation`,type:`object`,description:"What an entry click opens — the `{ mode, size, openNewTab, preventNavigation }` block a list view declares. With the key ABSENT a click opens nothing: this renderer supplies no drawer default. `mode` is an overlay (`drawer`, `modal`, `split`, `popover`), `new_window`, `page` or `none`, and a block written without `mode` takes the spec’s `page` default. `drawer`, `modal` and `popover` open the entry’s record in that overlay, but `split` opens nothing, because the timeline hands the split shell no main panel; `new_window` opens the record page in a new tab; `none` opens nothing. `page` opens the record page of the timeline’s `objectName` through the record navigator the host publishes (the console publishes one on its custom pages, record pages and list views); under a host that publishes none, such as an embedded renderer, or on a timeline that names no `objectName`, there is no record page to open and the click opens nothing. `preventNavigation: true` opens nothing whatever the mode, `openNewTab: true` opens the record page in a new tab and outranks every mode except `none`, and `size` sets the overlay width. On a timeline that names no `objectName`, `new_window` and `openNewTab` open no record page either: the new tab’s address is a slash and the entry’s `id` alone (its `_id` when it has no `id`, `undefined` when it has neither). A click handler from a parent view outranks the whole key."},{name:`timeline`,type:`object`,description:"Timeline configuration, the author face — the same block `ListViewSchema.timeline` declares: { startDateField, endDateField, titleField, groupByField, colorField, scale }. The flat top-level spellings beside it are the runtime handoff, not a second authoring spelling. On entries composed from records, `startDateField` is the entry’s date, `endDateField` the end printed after it, `titleField` the title, `groupByField` the field whose value heads each group (without it, entries group into date buckets), and `colorField` the field whose option colour, or the value itself when it is a colour literal, paints the marker. Each outranks the flat key of the same binding, and `titleField` / `startDateField` outrank `mapping`’s `title` / `date`. `scale` sets the axis unit of the gantt branch, which on this block draws authored `items` only."},{name:`limit`,type:`number`,description:"Maximum number of records loaded onto the rail (row cap); lowered to the query's top-level `$top` (renderer default 100). A timeline renders one rail with no pagination control, so this is the author's window rather than a page size. A value that is not a positive integer is ignored with a console warning, and the default cap applies."},{name:`data`,type:`array`,description:"Pre-fetched records — read FIRST as the rail's row source, ahead of the data-scope binding and the fetch, and composed into entries through the same `timeline` field bindings a fetched row takes; authoring it suppresses the object query entirely. Distinct from `items`, which is the already-composed entry shape and wins over this key when both are written."},{name:`items`,type:`array`,description:"Static inline entries — read ahead of every record source, `data` above included, and bypasses the object query entirely (the renderer becomes a pass-through). Each entry is the kind this node's `variant` selects: a feed entry `{ time?, title, description?, variant?, icon?, content?, className? }` (`variant` absent / `vertical` / `horizontal`), or a gantt row `{ label, items? }` (`variant: 'gantt'`) whose bars are `{ title?, startDate?, endDate?, variant? }`, each date a string or epoch milliseconds. These are `@object-ui/types`'s `TimelineFeedItem` and `TimelineGanttItem`. They are drawn as written: the `timeline` block’s field bindings, `mapping` and `descriptionField` do not apply to them."},{name:`dateFormat`,type:`enum`,enum:[`short`,`long`,`iso`],description:"How each entry's date is rendered (renderer default `short`): `short` / `long` are locale-formatted, `iso` is the locale-free machine form."},{name:`rowLabel`,type:`string`,description:"Header label for the gantt row column — read by the gantt branch only, which on this block needs authored `items`. Without it the header shows the default label."},{name:`minDate`,type:`string`,description:"Pin the gantt axis start (ISO `yyyy-mm-dd`) instead of deriving it from the rows; only a non-empty value is honoured. A value that is not a date, or a `minDate` after `maxDate`, refuses the chart with a diagnostic naming it."},{name:`maxDate`,type:`string`,description:"Pin the gantt axis end (ISO `yyyy-mm-dd`) instead of deriving it from the rows; only a non-empty value is honoured. A value that is not a date, or a `maxDate` before `minDate`, refuses the chart with a diagnostic naming it."},{name:`descriptionField`,type:`string`,description:"Field rendered as each entry's description (renderer default `description`). It is declared flat because the `timeline` block has no member for it, and `mapping.description` outranks it when both are written."},{name:`mapping`,type:`object`,description:"Record-to-entry field mapping `{ title?, date?, description?, variant? }`, each a field name — the binding record read BETWEEN the `timeline` block and the flat fallbacks. Its `variant` member (the field whose value picks each marker colour, renderer default `variant`) is the only spelling that binding has. On the vertical rail a colour that `timeline.colorField` resolves for an entry outranks that marker colour."}];i.ComponentRegistry.register(`object-timeline`,Ce,{namespace:`plugin-timeline`,label:`Object Timeline`,category:`view`,inputs:[...we]}),i.ComponentRegistry.register(`timeline`,Ce,{namespace:`view`,label:`Timeline View`,category:`view`,inputs:[...we]}),e.ObjectTimeline=H,e.ObjectTimelineRenderer=Ce,e.TIMELINE_SCALES=x,e.Timeline=U,e.TimelineContent=he,e.TimelineDescription=Y,e.TimelineGantt=_e,e.TimelineGanttBar=be,e.TimelineGanttBarContent=xe,e.TimelineGanttGrid=Q,e.TimelineGanttHeader=ve,e.TimelineGanttLabel=ye,e.TimelineGanttRow=$,e.TimelineGanttRowLabels=Z,e.TimelineHorizontal=X,e.TimelineHorizontalItem=ge,e.TimelineItem=G,e.TimelineMarker=K,e.TimelineRenderer=B,e.TimelineTime=J,e.TimelineTitle=q,e.generateTimeScaleHeaders=j,e.resolveTimelineScale=S,e.timelineItemVariants=W,e.timelineMarkerVariants=me});
|
package/dist/renderHandoff.d.ts
CHANGED
|
@@ -33,18 +33,31 @@ export interface TimelineRenderFeedItem extends Omit<TimelineFeedItem, 'title' |
|
|
|
33
33
|
_data?: unknown;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* `TimelineSchema` with every declared member kept
|
|
37
|
-
* handoff element.
|
|
36
|
+
* `TimelineSchema` with every declared member kept, `items` widened to the
|
|
37
|
+
* handoff element, and the click slot `ObjectTimeline` installs.
|
|
38
38
|
*
|
|
39
|
-
* Spelled as a key-remapping mapped type and ⛔ not as `Omit
|
|
40
|
-
*
|
|
41
|
-
* `string` and `Omit`
|
|
42
|
-
* dropping every declared member. A homomorphic mapped
|
|
43
|
-
* members and
|
|
39
|
+
* Spelled as a key-remapping mapped type and ⛔ not as `Omit`. It was written
|
|
40
|
+
* while `TimelineSchema` inherited `BaseSchema`'s string index signature, under
|
|
41
|
+
* which `keyof` resolved to `string` and `Omit` collapsed the whole interface
|
|
42
|
+
* into that signature, dropping every declared member. A homomorphic mapped
|
|
43
|
+
* type maps the declared members and any index signature separately, so only
|
|
44
|
+
* `items` leaves whether or not a signature is present (objectui#8347 removed
|
|
45
|
+
* `BaseSchema`'s).
|
|
44
46
|
*/
|
|
45
47
|
export type TimelineRenderSchema = {
|
|
46
48
|
[K in keyof TimelineSchema as K extends 'items' ? never : K]: TimelineSchema[K];
|
|
47
49
|
} & {
|
|
48
50
|
items?: Array<TimelineRenderFeedItem | TimelineGanttItem>;
|
|
51
|
+
/**
|
|
52
|
+
* The click handler `ObjectTimeline` composes onto the schema it hands over
|
|
53
|
+
* (it resolves the item's record and fires the overlay navigation). A runtime
|
|
54
|
+
* slot, not authorable metadata: it stays off `TimelineSchema` on purpose,
|
|
55
|
+
* per the objectui#6170 docblock in `@object-ui/types` (`data-display.ts`).
|
|
56
|
+
* While `BaseSchema` carried `[key: string]: any` the renderer's read of it
|
|
57
|
+
* compiled as `any`; objectui#8347 removed the signature, so it is typed here,
|
|
58
|
+
* where its only producer and its only consumer live. The gantt branch also
|
|
59
|
+
* passes the authored row and both indices.
|
|
60
|
+
*/
|
|
61
|
+
onItemClick?: (item: unknown, authored?: unknown, rowIndex?: number, itemIndex?: number) => void;
|
|
49
62
|
};
|
|
50
63
|
//# sourceMappingURL=renderHandoff.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderHandoff.d.ts","sourceRoot":"","sources":["../src/renderHandoff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE5F,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAClG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,sEAAsE;IACtE,IAAI,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAChC,uFAAuF;IACvF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"renderHandoff.d.ts","sourceRoot":"","sources":["../src/renderHandoff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE5F,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAClG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,sEAAsE;IACtE,IAAI,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAChC,uFAAuF;IACvF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,oBAAoB,GAAG;KAChC,CAAC,IAAI,MAAM,cAAc,IAAI,CAAC,SAAS,OAAO,GAAG,KAAK,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC;CAChF,GAAG;IACF,KAAK,CAAC,EAAE,KAAK,CAAC,sBAAsB,GAAG,iBAAiB,CAAC,CAAC;IAC1D;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAClG,CAAC"}
|
package/dist/renderer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAsB5D,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAGlC;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAE9C,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAGxE;AA2RD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAa,EACrB,CAAC,GAAE,iBAA4C,GAC9C,MAAM,EAAE,CAGV;
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAsB5D,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAGlC;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAE9C,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAGxE;AA2RD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAa,EACrB,CAAC,GAAE,iBAA4C,GAC9C,MAAM,EAAE,CAGV;AAilCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAM,gBAAgB,GAAI,4CAA4C;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,6BAmXlJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTimelineTranslation.d.ts","sourceRoot":"","sources":["../src/useTimelineTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"useTimelineTranslation.d.ts","sourceRoot":"","sources":["../src/useTimelineTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmFhE,CAAC;AAIF;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;AAE1F;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBAIpC,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;4BAtIlC,CAAC;;;;;CAyID,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-timeline",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Timeline component plugin for Object UI",
|
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@objectstack/spec": "^
|
|
27
|
+
"@objectstack/spec": "^18.0.0",
|
|
28
28
|
"class-variance-authority": "^0.7.1",
|
|
29
29
|
"zod": "^4.4.3",
|
|
30
|
-
"@object-ui/components": "
|
|
31
|
-
"@object-ui/
|
|
32
|
-
"@object-ui/
|
|
33
|
-
"@object-ui/mobile": "
|
|
34
|
-
"@object-ui/permissions": "
|
|
35
|
-
"@object-ui/react": "
|
|
36
|
-
"@object-ui/types": "
|
|
30
|
+
"@object-ui/components": "18.0.0",
|
|
31
|
+
"@object-ui/i18n": "18.0.0",
|
|
32
|
+
"@object-ui/core": "18.0.0",
|
|
33
|
+
"@object-ui/mobile": "18.0.0",
|
|
34
|
+
"@object-ui/permissions": "18.0.0",
|
|
35
|
+
"@object-ui/react": "18.0.0",
|
|
36
|
+
"@object-ui/types": "18.0.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"typescript": "^6.0.3",
|
|
47
47
|
"vite": "^8.2.1",
|
|
48
48
|
"vite-plugin-dts": "^5.0.3",
|
|
49
|
-
"@object-ui/data-objectstack": "
|
|
50
|
-
"@object-ui/sdui-parser": "
|
|
49
|
+
"@object-ui/data-objectstack": "18.0.0",
|
|
50
|
+
"@object-ui/sdui-parser": "18.0.0",
|
|
51
51
|
"@object-ui/test-support": "17.4.0"
|
|
52
52
|
},
|
|
53
53
|
"keywords": [
|