@fayz-ai/plugin-tasks 0.8.0 → 0.9.0-next.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.
@@ -1 +1 @@
1
- {"version":3,"file":"TaskDetail.d.ts","sourceRoot":"","sources":["../../src/components/TaskDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAA;AAsB/D,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,qBAiKxD"}
1
+ {"version":3,"file":"TaskDetail.d.ts","sourceRoot":"","sources":["../../src/components/TaskDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAA;AA4B/D,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,qBAoLxD"}
@@ -1,3 +1,4 @@
1
1
  import React from 'react';
2
+ /** Tasks as a sheet — the fallback where the shell has no right rail. */
2
3
  export declare function TasksDrawer(): React.JSX.Element;
3
4
  //# sourceMappingURL=TasksDrawer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TasksDrawer.d.ts","sourceRoot":"","sources":["../../src/components/TasksDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAgBzB,wBAAgB,WAAW,sBA6E1B"}
1
+ {"version":3,"file":"TasksDrawer.d.ts","sourceRoot":"","sources":["../../src/components/TasksDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,yEAAyE;AACzE,wBAAgB,WAAW,sBAsB1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"TasksGeneralSettings.d.ts","sourceRoot":"","sources":["../../src/components/TasksGeneralSettings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,wBAAgB,oBAAoB,sBAyBnC"}
1
+ {"version":3,"file":"TasksGeneralSettings.d.ts","sourceRoot":"","sources":["../../src/components/TasksGeneralSettings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,wBAAgB,oBAAoB,sBA8BnC"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ /** The task list with no box around it — shared by the sheet and the shell's
3
+ * right-rail tab. */
4
+ export declare function TasksPanel(): React.JSX.Element;
5
+ /** One-line summary of what needs attention ("3 atrasadas · 2 para hoje"). */
6
+ export declare function useTasksSummaryLine(): string;
7
+ //# sourceMappingURL=TasksPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TasksPanel.d.ts","sourceRoot":"","sources":["../../src/components/TasksPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAazB;sBACsB;AACtB,wBAAgB,UAAU,sBAiEzB;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,IAAI,MAAM,CAU5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"TasksTopbarButton.d.ts","sourceRoot":"","sources":["../../src/components/TasksTopbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAA;AAIxC,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAEhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEjD,UAAU,sBAAsB;IAC9B,MAAM,EAAE;QACN,WAAW,EAAE,mBAAmB,CAAA;QAChC,aAAa,EAAE,iBAAiB,CAAA;QAChC,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;KACnC,CAAA;CACF;AAED,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,sBAAsB,qBASnE"}
1
+ {"version":3,"file":"TasksTopbarButton.d.ts","sourceRoot":"","sources":["../../src/components/TasksTopbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAA;AAMxC,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAGhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEjD,UAAU,sBAAsB;IAC9B,MAAM,EAAE;QACN,WAAW,EAAE,mBAAmB,CAAA;QAChC,aAAa,EAAE,iBAAiB,CAAA;QAChC,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;KACnC,CAAA;CACF;AAED,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,sBAAsB,qBA4CnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC5E,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAe3C,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACnC,mBAAmB;IACnB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,kBAAkB;IAClB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,iBAAiB,CAAA;IAChC,yDAAyD;IACzD,eAAe,CAAC,EAAE,YAAY,CAAA;CAC/B;AA2BD,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,cAAc,CAqG9E;AAMD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,YAAY,EACV,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EACvD,eAAe,EAAE,eAAe,EAAE,SAAS,GAC5C,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC5E,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAgB3C,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACnC,mBAAmB;IACnB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,kBAAkB;IAClB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,iBAAiB,CAAA;IAChC,yDAAyD;IACzD,eAAe,CAAC,EAAE,YAAY,CAAA;CAC/B;AA2BD,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,cAAc,CAoI9E;AAMD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,YAAY,EACV,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EACvD,eAAe,EAAE,eAAe,EAAE,SAAS,GAC5C,MAAM,SAAS,CAAA"}
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import React4, { useEffect, useState, useCallback } from 'react';
2
- import { createPluginContext, dedup } from '@fayz-ai/saas';
2
+ import { createPluginContext, registerNotesTasksAdapter, NOTE_LABEL_PREFIX, dedup, useRightRailStore, useRightRailPanel, useTenantPluginSettings, useDelegateToAssistant } from '@fayz-ai/saas';
3
3
  import { registerTranslations, createSafeDataProvider, useTranslation, getActiveTenantId, getSupabaseClientOptional } from '@fayz-ai/core';
4
4
  import { createStore } from 'zustand/vanilla';
5
- import { jsxs, jsx } from 'react/jsx-runtime';
6
- import { CheckSquare, ClipboardList, Plus, ArrowLeft, ChevronDown, Calendar, Trash2, ListChecks, ChevronRight, AlertTriangle, ArrowUp, Minus, ArrowDown } from 'lucide-react';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+ import { CheckSquare, ClipboardList, Plus, ArrowLeft, Trash2, ChevronDown, Calendar, Sparkles, ListChecks, ChevronRight, AlertTriangle, ArrowUp, Minus, ArrowDown } from 'lucide-react';
7
7
  import { Button, cn, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, Checkbox } from '@fayz-ai/ui';
8
8
  import { useStore } from 'zustand';
9
9
 
@@ -400,6 +400,8 @@ var en = {
400
400
  "tasks.detail.delete": "Delete Task",
401
401
  "tasks.detail.deleteConfirm": "Are you sure you want to delete this task?",
402
402
  "tasks.detail.created": "Created",
403
+ "tasks.detail.chatWithAi": "Chat with AI",
404
+ "tasks.detail.chatWithAi.prompt": "Take over this task and help me resolve it now, using your tools when needed:",
403
405
  "tasks.detail.updated": "Updated",
404
406
  "tasks.detail.addSubtask": "Add subtask...",
405
407
  "tasks.detail.back": "Back to list",
@@ -442,6 +444,8 @@ var ptBR = {
442
444
  "tasks.detail.delete": "Excluir Tarefa",
443
445
  "tasks.detail.deleteConfirm": "Tem certeza que deseja excluir esta tarefa?",
444
446
  "tasks.detail.created": "Criada em",
447
+ "tasks.detail.chatWithAi": "Conversar com IA",
448
+ "tasks.detail.chatWithAi.prompt": "Assuma esta tarefa e me ajude a resolver agora, usando suas ferramentas quando precisar:",
445
449
  "tasks.detail.updated": "Atualizada em",
446
450
  "tasks.detail.addSubtask": "Adicionar subtarefa...",
447
451
  "tasks.detail.back": "Voltar \xE0 lista",
@@ -490,8 +494,12 @@ var tasksRegistries = [
490
494
  ]
491
495
  }
492
496
  ];
497
+ var TASKS_DEFAULTS = {
498
+ defaultPriority: "medium"
499
+ };
493
500
  function TasksGeneralSettings() {
494
501
  const t = useTranslation();
502
+ const s = useTenantPluginSettings("tasks", TASKS_DEFAULTS);
495
503
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
496
504
  /* @__PURE__ */ jsxs("div", { children: [
497
505
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-1", children: t("tasks.settings.general") }),
@@ -499,12 +507,20 @@ function TasksGeneralSettings() {
499
507
  ] }),
500
508
  /* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
501
509
  /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: t("tasks.settings.defaultPriority") }),
502
- /* @__PURE__ */ jsxs("select", { className: "w-full max-w-xs rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-sm", children: [
503
- /* @__PURE__ */ jsx("option", { value: "low", children: t("tasks.priority.low") }),
504
- /* @__PURE__ */ jsx("option", { value: "medium", selected: true, children: t("tasks.priority.medium") }),
505
- /* @__PURE__ */ jsx("option", { value: "high", children: t("tasks.priority.high") }),
506
- /* @__PURE__ */ jsx("option", { value: "urgent", children: t("tasks.priority.urgent") })
507
- ] })
510
+ /* @__PURE__ */ jsxs(
511
+ "select",
512
+ {
513
+ className: "w-full max-w-xs rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-sm",
514
+ value: s.get("defaultPriority"),
515
+ onChange: (e) => s.set("defaultPriority", e.target.value),
516
+ children: [
517
+ /* @__PURE__ */ jsx("option", { value: "low", children: t("tasks.priority.low") }),
518
+ /* @__PURE__ */ jsx("option", { value: "medium", children: t("tasks.priority.medium") }),
519
+ /* @__PURE__ */ jsx("option", { value: "high", children: t("tasks.priority.high") }),
520
+ /* @__PURE__ */ jsx("option", { value: "urgent", children: t("tasks.priority.urgent") })
521
+ ]
522
+ }
523
+ )
508
524
  ] }) })
509
525
  ] });
510
526
  }
@@ -724,8 +740,10 @@ var STATUS_DOT = {
724
740
  done: "bg-success",
725
741
  cancelled: "bg-muted-foreground/60"
726
742
  };
727
- function formatDate(iso) {
728
- return new Date(iso).toLocaleDateString(void 0, { month: "short", day: "numeric" });
743
+ function formatDateTime(iso) {
744
+ const d = new Date(iso);
745
+ const sameDay = d.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
746
+ return sameDay ? d.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" }) : d.toLocaleDateString(void 0, { day: "2-digit", month: "2-digit", year: "2-digit" });
729
747
  }
730
748
  function TaskDetail({ taskId }) {
731
749
  const t = useTranslation();
@@ -734,6 +752,7 @@ function TaskDetail({ taskId }) {
734
752
  const updateTask = useTasksStore((s) => s.updateTask);
735
753
  const deleteTask = useTasksStore((s) => s.deleteTask);
736
754
  const task = tasks.find((tt) => tt.id === taskId);
755
+ const delegate = useDelegateToAssistant();
737
756
  const [title, setTitle] = useState("");
738
757
  const [description, setDescription] = useState("");
739
758
  const [subtasks, setSubtasks] = useState([]);
@@ -767,17 +786,36 @@ function TaskDetail({ taskId }) {
767
786
  /* @__PURE__ */ jsx("button", { type: "button", onClick: () => selectTask(null), className: "mt-2 text-xs text-primary hover:underline", children: t("tasks.detail.back") })
768
787
  ] });
769
788
  }
770
- return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
771
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
772
- /* @__PURE__ */ jsx(
773
- "button",
774
- {
775
- type: "button",
776
- onClick: () => selectTask(null),
777
- className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground transition-colors",
778
- children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" })
779
- }
780
- ),
789
+ return (
790
+ // Same frame as the Notes editor: header row with back + icon actions,
791
+ // full-bleed px-4 content, sectioned by hairlines, thin timestamp footer.
792
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-full flex-col", children: [
793
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 border-b border-border/40 px-2 py-1.5", children: [
794
+ /* @__PURE__ */ jsxs(
795
+ "button",
796
+ {
797
+ type: "button",
798
+ onClick: () => selectTask(null),
799
+ className: "inline-flex items-center gap-1 rounded-lg px-1.5 py-1 text-[11.5px] text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
800
+ children: [
801
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5" }),
802
+ t("tasks.drawer.title")
803
+ ]
804
+ }
805
+ ),
806
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
807
+ /* @__PURE__ */ jsx(
808
+ "button",
809
+ {
810
+ type: "button",
811
+ onClick: handleDelete,
812
+ "aria-label": t("tasks.detail.delete"),
813
+ title: t("tasks.detail.delete"),
814
+ className: "inline-flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted hover:text-destructive",
815
+ children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
816
+ }
817
+ )
818
+ ] }),
781
819
  /* @__PURE__ */ jsx(
782
820
  "input",
783
821
  {
@@ -788,101 +826,112 @@ function TaskDetail({ taskId }) {
788
826
  onKeyDown: (e) => {
789
827
  if (e.key === "Enter") e.currentTarget.blur();
790
828
  },
791
- className: "flex-1 bg-transparent text-sm font-semibold outline-none"
829
+ className: "bg-transparent px-4 pt-3 text-sm font-semibold text-foreground outline-none"
792
830
  }
793
- )
794
- ] }),
795
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
796
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
797
- /* @__PURE__ */ jsx(
798
- "select",
799
- {
800
- value: task.status,
801
- onChange: (e) => updateTask(task.id, { status: e.target.value }),
802
- className: "appearance-none rounded-full border bg-background pl-5 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
803
- children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: t(`tasks.status.${s}`) }, s))
804
- }
805
- ),
806
- /* @__PURE__ */ jsx("span", { className: `absolute left-2 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full ${STATUS_DOT[task.status]}` }),
807
- /* @__PURE__ */ jsx(ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
808
- ] }),
809
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
810
- /* @__PURE__ */ jsx(
811
- "select",
812
- {
813
- value: task.priority,
814
- onChange: (e) => updateTask(task.id, { priority: e.target.value }),
815
- className: "appearance-none rounded-full border bg-background pl-2 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
816
- children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: t(`tasks.priority.${p}`) }, p))
817
- }
818
- ),
819
- /* @__PURE__ */ jsx(ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
820
- ] }),
821
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
822
- /* @__PURE__ */ jsx(
823
- "input",
824
- {
825
- type: "date",
826
- value: task.dueDate ?? "",
827
- onChange: (e) => updateTask(task.id, { dueDate: e.target.value || null }),
828
- className: "appearance-none rounded-full border bg-background pl-6 pr-2 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors w-[120px]"
829
- }
830
- ),
831
- /* @__PURE__ */ jsx(Calendar, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
832
- ] }),
833
- task.labels.length > 0 && /* @__PURE__ */ jsx(TaskLabelBadges, { labelIds: task.labels, max: 3 })
834
- ] }),
835
- /* @__PURE__ */ jsx(
836
- "textarea",
837
- {
838
- value: description,
839
- onChange: (e) => setDescription(e.target.value),
840
- onBlur: handleDescriptionBlur,
841
- placeholder: t("tasks.detail.descriptionPlaceholder"),
842
- rows: 3,
843
- className: "w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-xs outline-none resize-none placeholder:text-muted-foreground/50 leading-relaxed"
844
- }
845
- ),
846
- /* @__PURE__ */ jsxs("div", { children: [
847
- /* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1", children: t("tasks.detail.subtasks") }),
848
- /* @__PURE__ */ jsxs("div", { className: "rounded-md border overflow-hidden", children: [
849
- /* @__PURE__ */ jsx(TaskQuickAdd, { parentId: task.id }),
850
- subtasks.length > 0 && /* @__PURE__ */ jsx("div", { className: "divide-y", children: subtasks.map((st) => /* @__PURE__ */ jsx(TaskCard, { task: st }, st.id)) })
851
- ] })
852
- ] }),
853
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-2 border-t", children: [
854
- /* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
855
- formatDate(task.createdAt),
856
- " \xB7 ",
857
- t("tasks.detail.updated"),
858
- " ",
859
- formatDate(task.updatedAt)
831
+ ),
832
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 px-4 pt-2", children: [
833
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
834
+ /* @__PURE__ */ jsx(
835
+ "select",
836
+ {
837
+ value: task.status,
838
+ onChange: (e) => updateTask(task.id, { status: e.target.value }),
839
+ className: "appearance-none rounded-full border bg-background pl-5 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
840
+ children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: t(`tasks.status.${s}`) }, s))
841
+ }
842
+ ),
843
+ /* @__PURE__ */ jsx("span", { className: `absolute left-2 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full ${STATUS_DOT[task.status]}` }),
844
+ /* @__PURE__ */ jsx(ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
845
+ ] }),
846
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
847
+ /* @__PURE__ */ jsx(
848
+ "select",
849
+ {
850
+ value: task.priority,
851
+ onChange: (e) => updateTask(task.id, { priority: e.target.value }),
852
+ className: "appearance-none rounded-full border bg-background pl-2 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
853
+ children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: t(`tasks.priority.${p}`) }, p))
854
+ }
855
+ ),
856
+ /* @__PURE__ */ jsx(ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
857
+ ] }),
858
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
859
+ /* @__PURE__ */ jsx(
860
+ "input",
861
+ {
862
+ type: "date",
863
+ value: task.dueDate ?? "",
864
+ onChange: (e) => updateTask(task.id, { dueDate: e.target.value || null }),
865
+ className: "appearance-none rounded-full border bg-background pl-6 pr-2 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors w-[120px]"
866
+ }
867
+ ),
868
+ /* @__PURE__ */ jsx(Calendar, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
869
+ ] }),
870
+ task.labels.length > 0 && /* @__PURE__ */ jsx(TaskLabelBadges, { labelIds: task.labels, max: 3 })
860
871
  ] }),
861
- /* @__PURE__ */ jsxs(
872
+ /* @__PURE__ */ jsx(
873
+ "textarea",
874
+ {
875
+ value: description,
876
+ onChange: (e) => setDescription(e.target.value),
877
+ onBlur: handleDescriptionBlur,
878
+ placeholder: t("tasks.detail.descriptionPlaceholder"),
879
+ className: "min-h-[72px] flex-1 resize-none bg-transparent px-4 py-3 text-sm leading-relaxed text-foreground outline-none placeholder:text-muted-foreground/60"
880
+ }
881
+ ),
882
+ /* @__PURE__ */ jsx("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsxs(
862
883
  "button",
863
884
  {
864
885
  type: "button",
865
- onClick: handleDelete,
866
- className: "inline-flex items-center gap-1 text-[11px] text-muted-foreground hover:text-destructive transition-colors",
886
+ onClick: () => delegate(
887
+ `${t("tasks.detail.chatWithAi.prompt")}
888
+
889
+ "${task.title}"${task.description ? `
890
+ ${task.description}` : ""}${task.dueDate ? `
891
+ (${t("tasks.detail.dueDate")}: ${task.dueDate})` : ""}`
892
+ ),
893
+ className: "group flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-primary via-primary/80 to-primary bg-[length:200%_100%] bg-left px-3 py-2 text-[13px] font-semibold text-primary-foreground shadow-sm transition-all duration-500 hover:bg-right hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
867
894
  children: [
868
- /* @__PURE__ */ jsx(Trash2, { className: "h-3 w-3" }),
869
- t("tasks.detail.delete")
895
+ /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4 transition-transform duration-300 group-hover:rotate-12" }),
896
+ t("tasks.detail.chatWithAi")
870
897
  ]
871
898
  }
872
- )
899
+ ) }),
900
+ /* @__PURE__ */ jsxs("div", { className: "border-t border-border/40 px-4 py-2.5", children: [
901
+ /* @__PURE__ */ jsxs("p", { className: "pb-1.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/60", children: [
902
+ t("tasks.detail.subtasks"),
903
+ subtasks.length > 0 ? ` \xB7 ${subtasks.length}` : ""
904
+ ] }),
905
+ /* @__PURE__ */ jsx("div", { className: "-mx-3", children: /* @__PURE__ */ jsx(TaskQuickAdd, { parentId: task.id }) }),
906
+ subtasks.length > 0 && /* @__PURE__ */ jsx("div", { className: "divide-y divide-border/40", children: subtasks.map((st) => /* @__PURE__ */ jsx(TaskCard, { task: st }, st.id)) })
907
+ ] }),
908
+ /* @__PURE__ */ jsxs("p", { className: "border-t border-border/40 px-4 py-1.5 text-[10px] text-muted-foreground/60", children: [
909
+ t("tasks.detail.created"),
910
+ " ",
911
+ formatDateTime(task.createdAt),
912
+ " \xB7 ",
913
+ t("tasks.detail.updated"),
914
+ " ",
915
+ formatDateTime(task.updatedAt)
916
+ ] })
873
917
  ] })
874
- ] });
918
+ );
875
919
  }
876
920
  var STATUS_ORDER = ["todo", "in_progress", "done", "cancelled"];
877
- function TasksDrawer() {
921
+ function TasksPanel() {
878
922
  const t = useTranslation();
879
- const drawerOpen = useTasksStore((s) => s.drawerOpen);
880
- const closeDrawer = useTasksStore((s) => s.closeDrawer);
881
923
  const selectedTaskId = useTasksStore((s) => s.selectedTaskId);
882
924
  const tasks = useTasksStore((s) => s.tasks);
883
925
  const tasksLoading = useTasksStore((s) => s.tasksLoading);
884
- const summary = useTasksStore((s) => s.summary);
885
926
  const activeFilter = useTasksStore((s) => s.activeFilter);
927
+ const fetchTasks = useTasksStore((s) => s.fetchTasks);
928
+ const fetchLabels = useTasksStore((s) => s.fetchLabels);
929
+ const fetchSummary = useTasksStore((s) => s.fetchSummary);
930
+ React4.useEffect(() => {
931
+ void fetchTasks();
932
+ void fetchLabels();
933
+ void fetchSummary();
934
+ }, [fetchTasks, fetchLabels, fetchSummary]);
886
935
  const grouped = React4.useMemo(() => {
887
936
  const map = /* @__PURE__ */ new Map();
888
937
  for (const s of STATUS_ORDER) map.set(s, []);
@@ -892,13 +941,32 @@ function TasksDrawer() {
892
941
  }
893
942
  return map;
894
943
  }, [tasks]);
895
- const summaryLine = React4.useMemo(() => {
944
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
945
+ !selectedTaskId && /* @__PURE__ */ jsx(TasksFilterBar, {}),
946
+ !selectedTaskId && /* @__PURE__ */ jsx(TaskQuickAdd, {}),
947
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: selectedTaskId ? /* @__PURE__ */ jsx(TaskDetail, { taskId: selectedTaskId }) : tasksLoading && tasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : tasks.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
948
+ /* @__PURE__ */ jsx(ClipboardList, { className: "mb-3 h-10 w-10 opacity-40" }),
949
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: t("tasks.empty") }),
950
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs", children: t("tasks.empty.description") })
951
+ ] }) : activeFilter !== "all" ? /* @__PURE__ */ jsx("div", { className: "py-1", children: tasks.map((task) => /* @__PURE__ */ jsx("div", { className: "px-2", children: /* @__PURE__ */ jsx(TaskCard, { task }) }, task.id)) }) : /* @__PURE__ */ jsx("div", { className: "space-y-2 py-2", children: STATUS_ORDER.filter((s) => s !== "cancelled" || (grouped.get(s)?.length ?? 0) > 0).map((status) => /* @__PURE__ */ jsx(TaskStatusGroup, { status, tasks: grouped.get(status) ?? [] }, status)) }) })
952
+ ] });
953
+ }
954
+ function useTasksSummaryLine() {
955
+ const t = useTranslation();
956
+ const summary = useTasksStore((s) => s.summary);
957
+ return React4.useMemo(() => {
896
958
  if (!summary) return "";
897
959
  const parts = [];
898
960
  if (summary.overdue > 0) parts.push(`${summary.overdue} ${t("tasks.summary.overdue")}`);
899
961
  if (summary.dueToday > 0) parts.push(`${summary.dueToday} ${t("tasks.summary.dueToday")}`);
900
962
  return parts.join(" \xB7 ");
901
963
  }, [summary, t]);
964
+ }
965
+ function TasksDrawer() {
966
+ const t = useTranslation();
967
+ const drawerOpen = useTasksStore((s) => s.drawerOpen);
968
+ const closeDrawer = useTasksStore((s) => s.closeDrawer);
969
+ const summaryLine = useTasksSummaryLine();
902
970
  return /* @__PURE__ */ jsx(Sheet, { open: drawerOpen, onOpenChange: (v) => {
903
971
  if (!v) closeDrawer();
904
972
  }, children: /* @__PURE__ */ jsxs(SheetContent, { width: "max-w-lg", overlay: "dim", children: [
@@ -906,26 +974,46 @@ function TasksDrawer() {
906
974
  /* @__PURE__ */ jsx(SheetTitle, { children: t("tasks.drawer.title") }),
907
975
  /* @__PURE__ */ jsx(SheetDescription, { children: summaryLine || t("tasks.drawer.subtitle") })
908
976
  ] }),
909
- !selectedTaskId && /* @__PURE__ */ jsx(TasksFilterBar, {}),
910
- !selectedTaskId && /* @__PURE__ */ jsx(TaskQuickAdd, {}),
911
- /* @__PURE__ */ jsx(SheetBody, { className: "px-0 py-0", children: selectedTaskId ? /* @__PURE__ */ jsx("div", { className: "px-5 py-4", children: /* @__PURE__ */ jsx(TaskDetail, { taskId: selectedTaskId }) }) : tasksLoading && tasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : tasks.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
912
- /* @__PURE__ */ jsx(ClipboardList, { className: "h-10 w-10 mb-3 opacity-40" }),
913
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: t("tasks.empty") }),
914
- /* @__PURE__ */ jsx("p", { className: "text-xs mt-1", children: t("tasks.empty.description") })
915
- ] }) : activeFilter !== "all" ? /* @__PURE__ */ jsx("div", { className: "py-1", children: tasks.map((task) => /* @__PURE__ */ jsx("div", { className: "px-2", children: /* @__PURE__ */ jsx(TaskCard, { task }) }, task.id)) }) : /* @__PURE__ */ jsx("div", { className: "py-2 space-y-2", children: STATUS_ORDER.filter((s) => s !== "cancelled" || (grouped.get(s)?.length ?? 0) > 0).map((status) => /* @__PURE__ */ jsx(TaskStatusGroup, { status, tasks: grouped.get(status) ?? [] }, status)) }) })
977
+ /* @__PURE__ */ jsx(SheetBody, { className: "flex flex-col px-0 py-0", children: /* @__PURE__ */ jsx(TasksPanel, {}) })
916
978
  ] }) });
917
979
  }
918
980
  function TasksTopbarButton({ config }) {
919
981
  const { tasksConfig, tasksProvider, tasksStore } = config;
982
+ const t = useTranslation();
983
+ const railMounted = useRightRailStore((s) => s.mounted);
984
+ const summary = useStore(tasksStore, (s) => s.summary);
985
+ const openCount = summary ? summary.todo + summary.inProgress : 0;
986
+ const Panel = React4.useMemo(() => {
987
+ const RailPanel = () => /* @__PURE__ */ jsx(TasksContextProvider, { config: tasksConfig, provider: tasksProvider, store: tasksStore, children: /* @__PURE__ */ jsx(TasksPanel, {}) });
988
+ RailPanel.displayName = "TasksRailPanel";
989
+ return RailPanel;
990
+ }, [tasksConfig, tasksProvider, tasksStore]);
991
+ useRightRailPanel(
992
+ React4.useMemo(
993
+ () => railMounted ? {
994
+ id: "tasks",
995
+ label: t("tasks.drawer.title") || "Tasks",
996
+ icon: CheckSquare,
997
+ order: 20,
998
+ badge: { count: openCount, tone: "destructive" },
999
+ Component: Panel
1000
+ } : null,
1001
+ [railMounted, t, Panel, openCount]
1002
+ )
1003
+ );
920
1004
  return /* @__PURE__ */ jsxs(TasksContextProvider, { config: tasksConfig, provider: tasksProvider, store: tasksStore, children: [
921
- /* @__PURE__ */ jsx(TasksTopbarButtonInner, { store: tasksStore }),
922
- /* @__PURE__ */ jsx(TasksDrawer, {})
1005
+ /* @__PURE__ */ jsx(TasksTopbarButtonInner, { store: tasksStore, railMounted }),
1006
+ !railMounted && /* @__PURE__ */ jsx(TasksDrawer, {})
923
1007
  ] });
924
1008
  }
925
- function TasksTopbarButtonInner({ store }) {
1009
+ function TasksTopbarButtonInner({
1010
+ store,
1011
+ railMounted
1012
+ }) {
926
1013
  const toggleDrawer = useStore(store, (s) => s.toggleDrawer);
927
1014
  const fetchSummary = useStore(store, (s) => s.fetchSummary);
928
1015
  const summary = useStore(store, (s) => s.summary);
1016
+ const togglePanel = useRightRailStore((s) => s.togglePanel);
929
1017
  useEffect(() => {
930
1018
  fetchSummary();
931
1019
  }, [fetchSummary]);
@@ -936,7 +1024,7 @@ function TasksTopbarButtonInner({ store }) {
936
1024
  variant: "ghost",
937
1025
  size: "icon",
938
1026
  className: cn("relative text-sidebar-foreground/70 hover:bg-sidebar/30 hover:text-sidebar-foreground"),
939
- onClick: toggleDrawer,
1027
+ onClick: () => railMounted ? togglePanel("tasks") : toggleDrawer(),
940
1028
  "aria-label": "Tasks",
941
1029
  children: [
942
1030
  /* @__PURE__ */ jsx(CheckSquare, { className: "h-5 w-5" }),
@@ -1055,6 +1143,30 @@ function createTasksPlugin(options) {
1055
1143
  () => createMockTasksProvider()
1056
1144
  );
1057
1145
  const store = createTasksStore(provider);
1146
+ registerNotesTasksAdapter({
1147
+ async createTodo({ title, noteId, noteTitle }) {
1148
+ const task = await provider.createTask({
1149
+ title,
1150
+ description: noteTitle ? `Nota: ${noteTitle}` : void 0,
1151
+ labels: [`${NOTE_LABEL_PREFIX}${noteId}`]
1152
+ });
1153
+ void store.getState().fetchSummary();
1154
+ return { id: task.id, title: task.title, done: task.status === "done" };
1155
+ },
1156
+ async listTodos(noteId) {
1157
+ const tasks = await provider.getTasks({});
1158
+ const label = `${NOTE_LABEL_PREFIX}${noteId}`;
1159
+ return tasks.filter((t) => t.labels.includes(label)).sort((a, b) => (a.status === "done" ? 1 : 0) - (b.status === "done" ? 1 : 0)).map((t) => ({ id: t.id, title: t.title, done: t.status === "done" }));
1160
+ },
1161
+ async toggleTodo(id, done) {
1162
+ await provider.updateTask(id, { status: done ? "done" : "todo" });
1163
+ void store.getState().fetchSummary();
1164
+ },
1165
+ async removeTodo(id) {
1166
+ await provider.deleteTask(id);
1167
+ void store.getState().fetchSummary();
1168
+ }
1169
+ });
1058
1170
  return {
1059
1171
  id: "tasks",
1060
1172
  name: config.labels.drawerTitle,