picosh 0.2.0 → 0.2.1

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/index.js +32 -44
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -44,83 +44,71 @@ function downloadImage(url) {
44
44
 
45
45
  // ─── AI waiting indicator ───────────────────────────────────────────────────
46
46
 
47
- // ANSIエスケープを除去してプロンプト判定
48
47
  const ANSI_RE = /\x1b\[[0-9;]*[mGKHF]/g;
49
- // Claude Code / 一般的なAI CLIのプロンプトパターン
50
48
  const PROMPT_RE = />\s*$|❯\s*$/;
51
-
52
49
  const timers = {};
50
+ const waitingState = {};
53
51
 
54
- exports.middleware = (store) => (next) => (action) => {
52
+ function setWaiting(uid, waiting) {
53
+ waitingState[uid] = waiting;
54
+ if (typeof window !== 'undefined') {
55
+ window.dispatchEvent(new CustomEvent('picosh-ai-waiting', {detail: {uid, waiting}}));
56
+ }
57
+ }
58
+
59
+ exports.middleware = () => (next) => (action) => {
55
60
  if (action.type === 'SESSION_ADD_DATA') {
56
61
  const {uid, data} = action;
57
62
  const clean = data.replace(ANSI_RE, '');
58
63
 
59
64
  clearTimeout(timers[uid]);
60
- // 待機中フラグを一旦解除
61
- store.dispatch({type: 'PICOSH_AI_WAITING', uid, waiting: false});
65
+ setWaiting(uid, false);
62
66
 
63
67
  timers[uid] = setTimeout(() => {
64
- if (PROMPT_RE.test(clean)) {
65
- store.dispatch({type: 'PICOSH_AI_WAITING', uid, waiting: true});
66
- }
68
+ if (PROMPT_RE.test(clean)) setWaiting(uid, true);
67
69
  }, 500);
68
70
  }
69
71
 
70
72
  if (action.type === 'SESSION_PTY_DATA') {
71
- const {uid} = action;
72
- clearTimeout(timers[uid]);
73
- store.dispatch({type: 'PICOSH_AI_WAITING', uid, waiting: false});
73
+ clearTimeout(timers[action.uid]);
74
+ setWaiting(action.uid, false);
74
75
  }
75
76
 
76
77
  return next(action);
77
78
  };
78
79
 
79
- exports.reduceUI = (state, action) => {
80
- if (action.type === 'PICOSH_AI_WAITING') {
81
- const waiting = state.get('picoshWaiting') || {};
82
- return state.set('picoshWaiting', {...waiting, [action.uid]: action.waiting});
83
- }
84
- return state;
85
- };
86
-
87
- exports.mapTermsState = (state, map) => {
88
- return Object.assign(map, {picoshWaiting: state.ui.get('picoshWaiting') || {}});
89
- };
90
-
91
- exports.getTabsProps = (parentProps, props) => {
92
- return Object.assign(props, {picoshWaiting: parentProps.picoshWaiting});
93
- };
94
-
95
- exports.getTabProps = (tab, parentProps, props) => {
96
- return Object.assign(props, {
97
- isAiWaiting: !!(parentProps.picoshWaiting && parentProps.picoshWaiting[props.uid]),
98
- });
99
- };
100
-
101
80
  exports.decorateTab = (Tab, {React}) => {
102
81
  return function PicoshTab(props) {
103
- const style = props.isAiWaiting ? {
104
- boxShadow: '0 0 8px 2px #4a9eff',
105
- borderRadius: '4px',
106
- animation: 'picosh-glow 1.5s ease-in-out infinite',
107
- } : {};
82
+ const [waiting, setWaitingState] = React.useState(!!waitingState[props.uid]);
83
+
84
+ React.useEffect(() => {
85
+ function onWaiting(e) {
86
+ if (e.detail.uid === props.uid) setWaitingState(e.detail.waiting);
87
+ }
88
+ window.addEventListener('picosh-ai-waiting', onWaiting);
89
+ return () => window.removeEventListener('picosh-ai-waiting', onWaiting);
90
+ }, [props.uid]);
108
91
 
109
92
  return React.createElement(
110
93
  'div',
111
94
  {style: {position: 'relative', display: 'contents'}},
112
- React.createElement(Tab, props),
113
- props.isAiWaiting && React.createElement('style', {key: 'glow-style'}, `
95
+ waiting && React.createElement('style', {key: 's'}, `
114
96
  @keyframes picosh-glow {
115
- 0%, 100% { opacity: 1; }
116
- 50% { opacity: 0.6; }
97
+ 0%, 100% { box-shadow: 0 0 6px 2px #4a9eff; }
98
+ 50% { box-shadow: 0 0 12px 4px #4a9eff; }
117
99
  }
118
100
  `),
101
+ React.createElement(Tab, Object.assign({}, props, {
102
+ style: Object.assign({}, props.style, waiting ? {
103
+ animation: 'picosh-glow 1.5s ease-in-out infinite',
104
+ borderRadius: '4px',
105
+ } : {}),
106
+ })),
119
107
  );
120
108
  };
121
109
  };
122
110
 
123
- // ─── term: image paste + glow wrapper ───────────────────────────────────────
111
+ // ─── image paste (term) ──────────────────────────────────────────────────────
124
112
 
125
113
  exports.decorateTerm = (Term, {React}) => {
126
114
  return class extends React.Component {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "picosh",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Hyper plugin: paste clipboard images as file paths",
5
5
  "main": "index.js",
6
6
  "license": "MIT",