@takemo101/mikan 0.0.7 → 0.0.8

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.
Files changed (2) hide show
  1. package/dist/bin.js +112 -62
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -107402,7 +107402,7 @@ var import_react20 = __toESM(require_react(), 1);
107402
107402
  // package.json
107403
107403
  var package_default = {
107404
107404
  name: "@takemo101/mikan",
107405
- version: "0.0.7",
107405
+ version: "0.0.8",
107406
107406
  private: false,
107407
107407
  type: "module",
107408
107408
  bin: {
@@ -107466,6 +107466,9 @@ function visibleDetailLineCount(viewportHeight) {
107466
107466
  return Math.max(1, viewportHeight - 8);
107467
107467
  }
107468
107468
  function footerText(mode) {
107469
+ if (mode === "note-modal") {
107470
+ return "Note | Enter newline | Ctrl+S save | Esc cancel";
107471
+ }
107469
107472
  if (mode === "modal") {
107470
107473
  return "Modal | enter confirm | esc cancel | ? keys";
107471
107474
  }
@@ -107986,7 +107989,9 @@ function moveSelection(model, selection, direction, options = {}) {
107986
107989
  detailOpen: false,
107987
107990
  moveOpen: false,
107988
107991
  noteOpen: false,
107989
- labelOpen: false
107992
+ noteDraft: undefined,
107993
+ labelOpen: false,
107994
+ message: selection.noteOpen ? undefined : selection.message
107990
107995
  };
107991
107996
  }
107992
107997
  if (direction === "move") {
@@ -107995,6 +108000,7 @@ function moveSelection(model, selection, direction, options = {}) {
107995
108000
  archiveOpen: false,
107996
108001
  detailOpen: false,
107997
108002
  noteOpen: false,
108003
+ noteDraft: undefined,
107998
108004
  labelOpen: false,
107999
108005
  moveOpen: true,
108000
108006
  moveTargetIndex: 0
@@ -108007,7 +108013,9 @@ function moveSelection(model, selection, direction, options = {}) {
108007
108013
  detailOpen: false,
108008
108014
  moveOpen: false,
108009
108015
  labelOpen: false,
108010
- noteOpen: true
108016
+ noteOpen: true,
108017
+ noteDraft: "",
108018
+ message: undefined
108011
108019
  };
108012
108020
  }
108013
108021
  if (direction === "edit-labels") {
@@ -108019,6 +108027,7 @@ function moveSelection(model, selection, direction, options = {}) {
108019
108027
  githubConfirmOpen: false,
108020
108028
  moveOpen: false,
108021
108029
  noteOpen: false,
108030
+ noteDraft: undefined,
108022
108031
  labelOpen: true,
108023
108032
  labelFocusIndex: 0,
108024
108033
  labelDraftIds: card?.labels.filter((label) => knownLabelIds.has(label)) ?? []
@@ -108030,6 +108039,7 @@ function moveSelection(model, selection, direction, options = {}) {
108030
108039
  archiveOpen: true,
108031
108040
  moveOpen: false,
108032
108041
  noteOpen: false,
108042
+ noteDraft: undefined,
108033
108043
  labelOpen: false,
108034
108044
  githubConfirmOpen: false
108035
108045
  };
@@ -108040,6 +108050,7 @@ function moveSelection(model, selection, direction, options = {}) {
108040
108050
  archiveOpen: false,
108041
108051
  moveOpen: false,
108042
108052
  noteOpen: false,
108053
+ noteDraft: undefined,
108043
108054
  labelOpen: false,
108044
108055
  githubConfirmOpen: true
108045
108056
  };
@@ -108093,28 +108104,17 @@ function toggleFocusedLabel(model, selection) {
108093
108104
  current.add(label.id);
108094
108105
  return { ...selection, labelDraftIds: [...current] };
108095
108106
  }
108096
- function applyNoteInput(selection, keyName2, shift = false) {
108097
- if (!selection.noteOpen || !keyName2)
108098
- return selection;
108099
- if (keyName2 === "backspace") {
108100
- return {
108101
- ...selection,
108102
- noteDraft: (selection.noteDraft ?? "").slice(0, -1)
108103
- };
108104
- }
108105
- const character = keyName2 === "space" ? " " : keyName2;
108106
- if (character.length !== 1)
108107
- return selection;
108108
- const value = shift && /[a-z]/.test(character) ? character.toUpperCase() : character;
108109
- return { ...selection, noteDraft: `${selection.noteDraft ?? ""}${value}` };
108110
- }
108111
108107
  function footerMode(selection) {
108112
- if (selection.moveOpen || selection.noteOpen || selection.labelOpen || selection.archiveOpen || selection.githubConfirmOpen) {
108108
+ if (selection.noteOpen)
108109
+ return "note-modal";
108110
+ if (selection.moveOpen || selection.labelOpen || selection.archiveOpen || selection.githubConfirmOpen) {
108113
108111
  return "modal";
108114
108112
  }
108115
108113
  return selection.detailOpen ? "detail" : "board";
108116
108114
  }
108117
- function keyToTuiAction(keyName2, shift = false) {
108115
+ function keyToTuiAction(keyName2, shift = false, ctrl = false) {
108116
+ if (ctrl && keyName2 === "s")
108117
+ return "save-note";
108118
108118
  if (shift && keyName2 === "h")
108119
108119
  return "move-left";
108120
108120
  if (shift && keyName2 === "l")
@@ -108195,8 +108195,8 @@ function buildNotePromptViewModel(model, selection) {
108195
108195
  return {
108196
108196
  title: `Append note to ${card.id}`,
108197
108197
  focused: Boolean(selection.noteOpen),
108198
- draft: selection.noteDraft ?? "",
108199
- hint: "enter append esc cancel"
108198
+ feedback: selection.message === "Note cannot be empty" ? selection.message : undefined,
108199
+ hint: "Enter newline | Ctrl+S save | Esc cancel"
108200
108200
  };
108201
108201
  }
108202
108202
  function buildLabelPromptViewModel(model, selection) {
@@ -108259,17 +108259,6 @@ function renderMoveInteraction(model, selection) {
108259
108259
  view.hint
108260
108260
  ];
108261
108261
  }
108262
- function renderNoteInteraction(model, selection) {
108263
- const view = buildNotePromptViewModel(model, selection);
108264
- if (!view)
108265
- return ["Append note", "No Issue selected"];
108266
- return [
108267
- view.title,
108268
- `Note: ${view.draft}`,
108269
- ...view.feedback ? [view.feedback] : [],
108270
- view.hint
108271
- ];
108272
- }
108273
108262
  function renderLabelInteraction(model, selection) {
108274
108263
  const view = buildLabelPromptViewModel(model, selection);
108275
108264
  if (!view)
@@ -108314,6 +108303,7 @@ function renderKeyHelp() {
108314
108303
  "H/L move Issue",
108315
108304
  "m move menu",
108316
108305
  "n append Note",
108306
+ "note: enter newline, ctrl+s save",
108317
108307
  "e edit Labels",
108318
108308
  "a archive Issue",
108319
108309
  "g GitHub Mirror",
@@ -108334,13 +108324,50 @@ function MovePrompt(props) {
108334
108324
  });
108335
108325
  }
108336
108326
  function NotePrompt(props) {
108337
- return renderModalText({
108327
+ const view = buildNotePromptViewModel(props.model, props.selection);
108328
+ if (!view) {
108329
+ return renderModalText({
108330
+ theme: props.theme,
108331
+ backdropId: "note-modal-backdrop",
108332
+ panelId: "note-prompt",
108333
+ title: "Append Note",
108334
+ content: ["Append note", "No Issue selected"]
108335
+ });
108336
+ }
108337
+ const initialValue = props.selection.noteDraft ?? "";
108338
+ return renderModalShell({
108338
108339
  theme: props.theme,
108339
108340
  backdropId: "note-modal-backdrop",
108340
108341
  panelId: "note-prompt",
108341
108342
  title: "Append Note",
108342
- content: renderNoteInteraction(props.model, props.selection)
108343
- });
108343
+ panelStyle: { height: view.feedback ? 14 : 13 }
108344
+ }, import_react3.default.createElement("text", {
108345
+ content: [view.title, "", "Note:"].join(`
108346
+ `)
108347
+ }), import_react3.default.createElement("textarea", {
108348
+ id: "note-textarea",
108349
+ ref: props.noteTextareaRef,
108350
+ focused: true,
108351
+ initialValue,
108352
+ placeholder: "Write a Note...",
108353
+ height: 5,
108354
+ wrapMode: "word",
108355
+ keyBindings: [{ name: "s", ctrl: true, action: "submit" }],
108356
+ onSubmit: () => {
108357
+ props.onNoteSubmit?.(props.noteTextareaRef?.current?.plainText ?? "");
108358
+ },
108359
+ style: {
108360
+ alignSelf: "stretch",
108361
+ backgroundColor: props.theme?.base.canvas,
108362
+ textColor: props.theme?.base.text,
108363
+ focusedBackgroundColor: props.theme?.base.canvas,
108364
+ focusedTextColor: props.theme?.base.text,
108365
+ width: "auto"
108366
+ }
108367
+ }), import_react3.default.createElement("text", {
108368
+ content: ["", ...view.feedback ? [view.feedback] : [], view.hint].join(`
108369
+ `)
108370
+ }));
108344
108371
  }
108345
108372
  function LabelPrompt(props) {
108346
108373
  return renderModalText({
@@ -108370,6 +108397,12 @@ function GitHubMirrorPrompt(props) {
108370
108397
  });
108371
108398
  }
108372
108399
  function renderModalText(options) {
108400
+ return renderModalShell(options, import_react3.default.createElement("text", {
108401
+ content: options.content.join(`
108402
+ `)
108403
+ }));
108404
+ }
108405
+ function renderModalShell(options, ...children) {
108373
108406
  const theme = options.theme ?? buildTuiTheme();
108374
108407
  return import_react3.default.createElement("box", {
108375
108408
  id: options.backdropId,
@@ -108382,10 +108415,7 @@ function renderModalText(options) {
108382
108415
  ...modalStyle(theme),
108383
108416
  ...options.panelStyle ?? {}
108384
108417
  }
108385
- }, import_react3.default.createElement("text", {
108386
- content: options.content.join(`
108387
- `)
108388
- })));
108418
+ }, ...children));
108389
108419
  }
108390
108420
  function modalBackdropStyle(_theme) {
108391
108421
  return {
@@ -108765,7 +108795,7 @@ function appendSelectedIssueNote(options) {
108765
108795
  return {
108766
108796
  ok: false,
108767
108797
  model: options.model,
108768
- selection: { ...options.selection, noteOpen: false },
108798
+ selection: { ...options.selection, noteOpen: true },
108769
108799
  message: "Note cannot be empty"
108770
108800
  };
108771
108801
  }
@@ -108812,7 +108842,8 @@ function appendSelectedIssueNote(options) {
108812
108842
  selection: {
108813
108843
  ...selection,
108814
108844
  detailOpen: options.selection.detailOpen,
108815
- noteOpen: false
108845
+ noteOpen: false,
108846
+ noteDraft: undefined
108816
108847
  },
108817
108848
  message: `${card.id} note appended`
108818
108849
  };
@@ -108829,7 +108860,9 @@ function TuiAppView({
108829
108860
  theme = buildTuiTheme(),
108830
108861
  viewportHeight,
108831
108862
  viewportWidth,
108832
- columns
108863
+ columns,
108864
+ noteTextareaRef,
108865
+ onNoteSubmit
108833
108866
  }) {
108834
108867
  const details = selection.detailOpen ? getSelectedDetails(model, selection) : undefined;
108835
108868
  return import_react20.default.createElement("box", {
@@ -108855,7 +108888,13 @@ function TuiAppView({
108855
108888
  viewportHeight,
108856
108889
  viewportWidth,
108857
108890
  columns
108858
- })), selection.moveOpen ? import_react20.default.createElement(MovePrompt, { model, selection, theme }) : undefined, selection.noteOpen ? import_react20.default.createElement(NotePrompt, { model, selection, theme }) : undefined, selection.labelOpen ? import_react20.default.createElement(LabelPrompt, { model, selection, theme }) : undefined, selection.archiveOpen ? import_react20.default.createElement(ArchivePrompt, { model, selection, theme }) : undefined, selection.githubConfirmOpen ? import_react20.default.createElement(GitHubMirrorPrompt, { model, selection, theme }) : undefined, selection.warningsOpen ? import_react20.default.createElement(WarningPanel, { model, theme }) : undefined, selection.helpOpen ? import_react20.default.createElement(HelpPanel, { theme }) : undefined, import_react20.default.createElement(Footer, {
108891
+ })), selection.moveOpen ? import_react20.default.createElement(MovePrompt, { model, selection, theme }) : undefined, selection.noteOpen ? import_react20.default.createElement(NotePrompt, {
108892
+ model,
108893
+ selection,
108894
+ theme,
108895
+ noteTextareaRef,
108896
+ onNoteSubmit
108897
+ }) : undefined, selection.labelOpen ? import_react20.default.createElement(LabelPrompt, { model, selection, theme }) : undefined, selection.archiveOpen ? import_react20.default.createElement(ArchivePrompt, { model, selection, theme }) : undefined, selection.githubConfirmOpen ? import_react20.default.createElement(GitHubMirrorPrompt, { model, selection, theme }) : undefined, selection.warningsOpen ? import_react20.default.createElement(WarningPanel, { model, theme }) : undefined, selection.helpOpen ? import_react20.default.createElement(HelpPanel, { theme }) : undefined, import_react20.default.createElement(Footer, {
108859
108898
  message: selection.message,
108860
108899
  mode: footerMode(selection),
108861
108900
  theme
@@ -108889,6 +108928,19 @@ async function launchTui(options = {}) {
108889
108928
  const modelRef = import_react20.default.useRef(model);
108890
108929
  const selectionRef = import_react20.default.useRef(selection);
108891
108930
  const githubBusyRef = import_react20.default.useRef(false);
108931
+ const noteTextareaRef = import_react20.default.useRef(null);
108932
+ const submitNote = import_react20.default.useCallback((body) => {
108933
+ const result = appendSelectedIssueNote({
108934
+ cwd: options.cwd,
108935
+ model: modelRef.current,
108936
+ selection: selectionRef.current,
108937
+ body
108938
+ });
108939
+ modelRef.current = result.model;
108940
+ selectionRef.current = { ...result.selection, message: result.message };
108941
+ setModel(result.model);
108942
+ setSelection({ ...result.selection, message: result.message });
108943
+ }, []);
108892
108944
  modelRef.current = model;
108893
108945
  selectionRef.current = selection;
108894
108946
  import_react20.default.useEffect(() => {
@@ -108906,7 +108958,7 @@ async function launchTui(options = {}) {
108906
108958
  return () => clearInterval(interval);
108907
108959
  }, []);
108908
108960
  useKeyboard2((key) => {
108909
- const action = keyToTuiAction(key.name, key.shift);
108961
+ const action = keyToTuiAction(key.name, key.shift, key.ctrl);
108910
108962
  if (selection.helpOpen) {
108911
108963
  if (action === "escape" || action === "help") {
108912
108964
  setSelection((current) => moveSelection(model, current, action));
@@ -108914,26 +108966,10 @@ async function launchTui(options = {}) {
108914
108966
  return;
108915
108967
  }
108916
108968
  if (selection.noteOpen) {
108917
- if (action === "help") {
108918
- setSelection((current) => moveSelection(model, current, action));
108919
- return;
108920
- }
108921
108969
  if (action === "escape") {
108922
108970
  setSelection((current) => moveSelection(model, current, action));
108923
108971
  return;
108924
108972
  }
108925
- if (action === "enter") {
108926
- const result = appendSelectedIssueNote({
108927
- cwd: options.cwd,
108928
- model,
108929
- selection,
108930
- body: selection.noteDraft ?? ""
108931
- });
108932
- setModel(result.model);
108933
- setSelection({ ...result.selection, message: result.message });
108934
- return;
108935
- }
108936
- setSelection((current) => applyNoteInput(current, key.name, key.shift));
108937
108973
  return;
108938
108974
  }
108939
108975
  if (selection.archiveOpen) {
@@ -109066,6 +109102,8 @@ async function launchTui(options = {}) {
109066
109102
  setSelection((current) => moveSelection(model, current, action));
109067
109103
  return;
109068
109104
  }
109105
+ if (action === "save-note")
109106
+ return;
109069
109107
  if (action === "github") {
109070
109108
  if (githubBusyRef.current)
109071
109109
  return;
@@ -109098,7 +109136,9 @@ async function launchTui(options = {}) {
109098
109136
  selection,
109099
109137
  viewportHeight: renderer.height,
109100
109138
  viewportWidth: renderer.width,
109101
- columns: options.columns
109139
+ columns: options.columns,
109140
+ noteTextareaRef,
109141
+ onNoteSubmit: submitNote
109102
109142
  });
109103
109143
  }
109104
109144
  root.render(import_react20.default.createElement(App));
@@ -109833,6 +109873,10 @@ function helpText() {
109833
109873
  Usage:
109834
109874
  mikan <command> [options]
109835
109875
 
109876
+ Options:
109877
+ -v, --version Print mikan version
109878
+ -h, --help Show this help
109879
+
109836
109880
  Commands:
109837
109881
  init Create .mikan project files
109838
109882
  add Create an Issue
@@ -110063,6 +110107,9 @@ async function runCli(argv = process.argv.slice(2), options = {}) {
110063
110107
  const command = argv[0];
110064
110108
  if (!command || isHelpFlag(command))
110065
110109
  return ok2(helpText());
110110
+ if (isVersionFlag(command))
110111
+ return ok2(`${package_default.version}
110112
+ `);
110066
110113
  if (command === "help") {
110067
110114
  const topic = argv[1];
110068
110115
  return topic ? commandHelp(topic) : ok2(helpText());
@@ -110121,6 +110168,9 @@ Run \`mikan help tui\` for usage.`);
110121
110168
  return fail2(error51 instanceof Error ? error51.message : String(error51));
110122
110169
  }
110123
110170
  }
110171
+ function isVersionFlag(input) {
110172
+ return input === "-v" || input === "--version";
110173
+ }
110124
110174
  async function main(argv = process.argv.slice(2)) {
110125
110175
  const result = await runInteractiveCommand(argv, { cwd: process.cwd() });
110126
110176
  if (result.stdout)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takemo101/mikan",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {