Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@markprompt/react

Package Overview
Dependencies
Maintainers
1
Versions
145
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@markprompt/react - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

dist/footer.d.ts

5

dist/index.d.ts

@@ -1,2 +0,3 @@

import 'client-only';
export * from './Markprompt.js';
export { Context, Root, Trigger, Portal, Overlay, Content, Close, Title, Description, Form, Prompt, Answer, AutoScroller, References, } from './headless.js';
export { useMarkprompt } from './useMarkprompt.js';
//# sourceMappingURL=index.d.ts.map

4

dist/index.js

@@ -1,1 +0,3 @@

import"client-only";export*from'./Markprompt.js';
export { Context, Root, Trigger, Portal, Overlay, Content, Close, Title, Description, Form, Prompt, Answer, AutoScroller, References, } from './headless.js';
export { useMarkprompt } from './useMarkprompt.js';
//# sourceMappingURL=index.js.map

@@ -1,3 +0,3 @@

import { FC } from 'react';
import type { OpenAIModelId } from '@markprompt/core';
/// <reference types="react" />
import { OpenAIModelId } from '@markprompt/core';
type MarkpromptProps = {

@@ -13,3 +13,4 @@ projectKey: string;

};
export declare const Markprompt: FC<MarkpromptProps>;
export declare function Markprompt({ model, projectKey, iDontKnowMessage: _iDontKnowMessage, placeholder: _placeholder, autoScrollDisabled, didCompleteFirstQuery, onDark, completionsUrl, }: MarkpromptProps): JSX.Element;
export default Markprompt;
//# sourceMappingURL=Markprompt.d.ts.map

@@ -1,1 +0,113 @@

import n,{useCallback as A,useEffect as y,useRef as h,useState as m}from"react";import M from"classnames";import K from"remark-gfm";import T from"react-markdown";import{submitPrompt as z}from"@markprompt/core";const D=()=>n.createElement("span",{className:"caret animate-caret inline-block h-[15px] w-[8px] translate-y-[2px] translate-x-[2px] transform rounded-[1px] bg-fuchsia-500 shadow-[0_0px_3px_0px_rgba(217,70,219,0.9)]"}),o=({Component:s,children:l,...t})=>(s==="code"&&t.inline&&(t={...t,inline:"true"}),n.createElement(s,{...t,className:"markdown-node"},l,n.createElement(D,null))),L=({model:s,projectKey:l,iDontKnowMessage:t,placeholder:P,autoScrollDisabled:g,didCompleteFirstQuery:p,onDark:v,completionsUrl:b})=>{const[i,S]=m(void 0),[r,x]=m(""),[d,w]=m([]),[a,C]=m(!1),u=h(null),f=h(null),k=h(!1),N=t||"Sorry, I am not sure how to answer that.",E=P||"Ask me anything...",I=A(async e=>{e.preventDefault(),i&&(x(""),w([]),C(!0),await z(i,l,c=>x(_=>_+c),c=>w(c),{completionsUrl:b,iDontKnowMessage:N,model:s}),C(!1))},[i,l,b,N,s]);return y(()=>{if(g||!u.current||!f.current)return;const e=f.current.getBoundingClientRect();u.current.scrollTop=e.bottom},[r,a,g,d]),y(()=>{!a&&r.length>0&&(k.current||(k.current=!0,p==null||p()))},[a,r,p]),n.createElement("div",{className:"relative flex h-full flex-col"},n.createElement("div",{className:"h-12 border-b border-neutral-900"},n.createElement("form",{onSubmit:I},n.createElement("input",{value:i||"",type:"text",onChange:e=>S(e.target.value),placeholder:E,className:"w-full appearance-none rounded-md border-0 bg-transparent px-0 pt-1 pb-2 outline-none placeholder:text-neutral-500 focus:outline-none focus:ring-0",autoComplete:"off",autoCorrect:"off",autoCapitalize:"none",spellCheck:"false",autoFocus:!0}))),n.createElement("div",{className:M("absolute inset-x-0 bottom-0 z-10 h-10 bg-gradient-to-t",{"from-neutral-1000 to-neutral-1000/0":!v,"from-neutral-1100 to-neutral-1100/0":v})}),n.createElement("div",{ref:u,className:"hidden-scrollbar prose prose-sm absolute inset-x-0 bottom-0 top-12 z-0 max-w-full overflow-y-auto scroll-smooth py-4 pb-8 dark:prose-invert"},a&&!(r.length>0)&&n.createElement(D,null),n.createElement("div",{className:M("prompt-answer",{"prompt-answer-done":!a,"prompt-answer-loading":a})},n.createElement(T,{components:{p:e=>n.createElement(o,{Component:"p",...e}),span:e=>n.createElement(o,{Component:"span",...e}),h1:e=>n.createElement(o,{Component:"h1",...e}),h2:e=>n.createElement(o,{Component:"h2",...e}),h3:e=>n.createElement(o,{Component:"h3",...e}),h4:e=>n.createElement(o,{Component:"h4",...e}),h5:e=>n.createElement(o,{Component:"h5",...e}),h6:e=>n.createElement(o,{Component:"h6",...e}),pre:e=>n.createElement(o,{Component:"pre",...e}),code:e=>n.createElement(o,{Component:"code",...e}),td:e=>n.createElement(o,{Component:"td",...e})},remarkPlugins:[K]},r)),r.length>0&&d.length>0&&n.createElement("div",{className:"mt-8 border-t border-neutral-900 pt-4 text-sm text-neutral-500"},n.createElement("div",{className:"animate-slide-up"},"Summary generated from the following sources:",n.createElement("div",{className:"mt-4 flex w-full flex-row flex-wrap items-center gap-2"},d.map(e=>n.createElement("div",{key:`reference-${e}`,className:"cursor-pointer rounded-md border border-neutral-900 bg-neutral-1100 px-2 py-1 text-sm font-medium text-neutral-300 transition hover:border-neutral-800 hover:text-neutral-200"},e))))),n.createElement("div",{className:"h-8"}),n.createElement("div",{ref:f})))};var j=L;export{L as Markprompt,j as default};
import { submitPrompt } from '@markprompt/core';
import cn from 'classnames';
import React, { useCallback, useEffect, useRef, useState, } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
const Caret = () => {
return (React.createElement("span", { className: "caret animate-caret inline-block h-[15px] w-[8px] translate-y-[2px] translate-x-[2px] transform rounded-[1px] bg-fuchsia-500 shadow-[0_0px_3px_0px_rgba(217,70,219,0.9)]" }));
};
function WithCaret({ Component, children, ...rest }) {
if (Component === 'code' && rest.inline) {
// The code component mistakenly receives a prop `inline: true` which
// the DOM will complain about unless it's converted to a string.
rest = {
...rest,
inline: 'true',
};
}
return (React.createElement(Component, { ...rest, className: "markdown-node" },
children,
React.createElement(Caret, null)));
}
export function Markprompt({ model, projectKey, iDontKnowMessage: _iDontKnowMessage, placeholder: _placeholder, autoScrollDisabled, didCompleteFirstQuery, onDark, completionsUrl, }) {
const controller = useRef(new AbortController());
const [prompt, setPrompt] = useState(undefined);
const [answer, setAnswer] = useState('');
const [references, setReferences] = useState([]);
const [loading, setLoading] = useState(false);
const containerRef = useRef(null);
const answerContainerRef = useRef(null);
const _didCompleteFirstQuery = useRef(false);
const iDontKnowMessage = _iDontKnowMessage || 'Sorry, I am not sure how to answer that.';
const placeholder = _placeholder || 'Ask me anything...';
// abort requests on unmount
useEffect(() => {
const c = controller.current;
return () => c.abort();
}, []);
const handleSubmit = useCallback(async (e) => {
e.preventDefault();
if (!prompt) {
return;
}
setAnswer('');
setReferences([]);
setLoading(true);
await submitPrompt(prompt, projectKey, (chunk) => {
console.log('Got chunk', chunk);
setAnswer((prev) => prev + chunk);
return true;
}, (refs) => setReferences(refs), (error) => {
console.error(error);
}, {
completionsUrl: completionsUrl,
iDontKnowMessage: iDontKnowMessage,
model: model,
signal: controller.current.signal,
});
setLoading(false);
}, [prompt, projectKey, completionsUrl, iDontKnowMessage, model]);
useEffect(() => {
if (autoScrollDisabled ||
!containerRef.current ||
!answerContainerRef.current) {
return;
}
const childRect = answerContainerRef.current.getBoundingClientRect();
containerRef.current.scrollTop = childRect.bottom;
}, [answer, loading, autoScrollDisabled, references]);
useEffect(() => {
if (!loading && answer.length > 0) {
// This gets called after an answer has completed.
if (!_didCompleteFirstQuery.current) {
_didCompleteFirstQuery.current = true;
didCompleteFirstQuery?.();
}
}
}, [loading, answer, didCompleteFirstQuery]);
return (React.createElement("div", { className: "relative flex h-full flex-col" },
React.createElement("div", { className: "h-12 border-b border-neutral-900" },
React.createElement("form", { onSubmit: handleSubmit },
React.createElement("input", { value: prompt || '', type: "text", onChange: (e) => setPrompt(e.target.value), placeholder: placeholder, className: "w-full appearance-none rounded-md border-0 bg-transparent px-0 pt-1 pb-2 outline-none placeholder:text-neutral-500 focus:outline-none focus:ring-0", autoComplete: "off", autoCorrect: "off", autoCapitalize: "none", spellCheck: "false", autoFocus: true }))),
React.createElement("div", { className: cn('absolute inset-x-0 bottom-0 z-10 h-10 bg-gradient-to-t', {
'from-neutral-1000 to-neutral-1000/0': !onDark,
'from-neutral-1100 to-neutral-1100/0': onDark,
}) }),
React.createElement("div", { ref: containerRef, className: "hidden-scrollbar prose prose-sm absolute inset-x-0 bottom-0 top-12 z-0 max-w-full overflow-y-auto scroll-smooth py-4 pb-8 dark:prose-invert" },
loading && !(answer.length > 0) && React.createElement(Caret, null),
React.createElement("div", { className: cn('prompt-answer', {
'prompt-answer-done': !loading,
'prompt-answer-loading': loading,
}) },
React.createElement(ReactMarkdown, { components: {
p: (props) => React.createElement(WithCaret, { Component: "p", ...props }),
span: (props) => React.createElement(WithCaret, { Component: "span", ...props }),
h1: (props) => React.createElement(WithCaret, { Component: "h1", ...props }),
h2: (props) => React.createElement(WithCaret, { Component: "h2", ...props }),
h3: (props) => React.createElement(WithCaret, { Component: "h3", ...props }),
h4: (props) => React.createElement(WithCaret, { Component: "h4", ...props }),
h5: (props) => React.createElement(WithCaret, { Component: "h5", ...props }),
h6: (props) => React.createElement(WithCaret, { Component: "h6", ...props }),
pre: (props) => React.createElement(WithCaret, { Component: "pre", ...props }),
code: (props) => React.createElement(WithCaret, { Component: "code", ...props }),
td: (props) => React.createElement(WithCaret, { Component: "td", ...props }),
}, remarkPlugins: [remarkGfm] }, answer)),
answer.length > 0 && references.length > 0 && (React.createElement("div", { className: "mt-8 border-t border-neutral-900 pt-4 text-sm text-neutral-500" },
React.createElement("div", { className: "animate-slide-up" },
"Summary generated from the following sources:",
React.createElement("div", { className: "mt-4 flex w-full flex-row flex-wrap items-center gap-2" }, references.map((r) => (React.createElement("div", { key: `reference-${r}`, className: "cursor-pointer rounded-md border border-neutral-900 bg-neutral-1100 px-2 py-1 text-sm font-medium text-neutral-300 transition hover:border-neutral-800 hover:text-neutral-200" }, r))))))),
React.createElement("div", { className: "h-8" }),
React.createElement("div", { ref: answerContainerRef }))));
}
export default Markprompt;
//# sourceMappingURL=Markprompt.js.map
{
"name": "@markprompt/react",
"version": "0.2.1",
"description": "A React component for adding GPT-4 powered search using the Markprompt API.",
"main": "dist/index.cjs",
"typings": "dist/index.d.ts",
"module": "dist/markprompt.esm.js",
"version": "0.3.0",
"description": "A headless React component for adding GPT-4 powered search using the Markprompt API.",
"repository": {
"type": "git",
"url": "git+https://github.com/motifland/markprompt-js.git",
"directory": "packages/react"
},
"license": "MIT",
"sideEffects": false,
"type": "module",
"sideEffects": false,
"exports": "./dist/index.js",
"files": [

@@ -15,54 +18,25 @@ "README.md",

],
"exports": {
"import": "./dist/markprompt.esm.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
"scripts": {
"build": "tsc --build --clean && tsc --build",
"dev": "tsc --build --clean && tsc --build --watch",
"prepack": "tsc --build --clean && tsc --build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/motifland/markprompt.git",
"directory": "packages/react"
"dependencies": {
"@radix-ui/react-dialog": "^1.0.3",
"classnames": "^2.3.2",
"client-only": "^0.0.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"react-markdown": "^8.0.7",
"remark-gfm": "^3.0.1"
},
"publishConfig": {
"access": "public"
"devDependencies": {
"react": "^18.0.0"
},
"scripts": {
"prepublishOnly": "npm run build",
"build": "./scripts/build.sh --external:react --external:react-dom",
"clean": "rimraf ./dist"
},
"peerDependencies": {
"react": "^16 || ^17 || ^18",
"react-dom": "^16 || ^17 || ^18"
"react": "^16 || ^17 || ^18"
},
"devDependencies": {
"@swc/core": "^1.2.131",
"@swc/jest": "^0.2.17",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.0.0",
"@types/node": "^14.14.22",
"@types/react": "^17.0.43",
"@types/react-dom": "^17.0.14",
"esbuild": "^0.17.8",
"fast-glob": "^3.2.12",
"husky": "^4.3.8",
"jest": "26",
"lint-staged": "^12.2.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.6.2",
"prettier-plugin-tailwindcss": "^0.1.4",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"rimraf": "^3.0.2",
"snapshot-diff": "^0.8.1",
"tslib": "^2.3.1",
"typescript": "^4.9.5"
},
"dependencies": {
"classnames": "^2.3.2",
"client-only": "^0.0.1",
"react-markdown": "^8.0.6",
"remark-gfm": "^3.0.1",
"@markprompt/core": "0.2.1"
"publishConfig": {
"access": "public"
}
}

@@ -19,16 +19,10 @@ # Markprompt React

In [Motif](https://motif.land), paste the following import statement in an MDX, JSX or TSX file:
Install the `@markprompt/react` package via npm or yarn:
```jsx
import { Markprompt } from 'https://esm.sh/markprompt';
```
If you have a Node-based setup, install the `markprompt` package via npm or yarn:
```sh
# npm
npm install markprompt
npm install @markprompt/react
# Yarn
yarn add markprompt
yarn add @markprompt/react
```

@@ -41,3 +35,3 @@

```jsx
import { Markprompt } from 'markprompt';
import { Markprompt } from '@markprompt/react';

@@ -49,47 +43,11 @@ function MyPrompt() {

where `project-key` can be obtained in your project settings, and `model` is the identifier of the OpenAI model to use for completions. Supported models are:
where `<project-key>` can be obtained in your project settings
- Chat completions: `gpt-4` `gpt-4-0314` `gpt-4-32k` `gpt-4-32k-0314` `gpt-3.5-turbo` `gpt-3.5-turbo-0301`
- Completions: `text-davinci-003`, `text-davinci-002`, `text-curie-001`, `text-babbage-001`, `text-ada-001`, `davinci`, `curie`, `babbage`, `ada`
## Documentation
If no model is specified, `gpt-3.5-turbo` will be used.
The full documentation for the component can be found on the [Markprompt docs](https://markprompt.com/docs#web-component).
## Styling
The Markprompt component is styled using [Tailwind CSS](https://tailwindcss.com/), and therefore requires a working Tailwind configuration. We are planning to make it headless, for more flexible options.
## Configuration
You can pass the following props to the component:
| Prop | Default value | Description |
| ------------------ | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `projectKey` | | Your project&apos;s API key, found in the project settings. |
| `model` | `gpt-3.5-turbo` | The OpenAI completions model to use. Supported values: `gpt-4`, `gpt-4-0314`, `gpt-4-32k`, `gpt-4-32k-0314`, `gpt-3.5-turbo`, `gpt-3.5-turbo-0301`, `text-davinci-003`, `text-davinci-002`, `text-curie-001`, `text-babbage-001`, `text-ada-001`, `davinci`, `curie`, `babbage`, `ada` |
| settings. |
| `iDontKnowMessage` | _Sorry, I am not sure how to answer that._ | Fallback message in can no answer is found. |
| `placeholder` | _Ask me anything..._ | Message to show in the input box when no text has been entered. |
Example:
```jsx
<Markprompt
projectKey="..."
model="..."
iDontKnowMessage="Sorry, I don't know!"
placeholder="Ask Acme docs..."
/>
```
## Whitelisting your domain
Usage of the [Markprompt API](https://markprompt.com) is subject to quotas, depending on the plan you have subscribed to. Markprompt has systems in place to detect abuse and excessive usage, but we nevertheless recommend being cautious when offering a prompt interface on a public website. In any case, when using the production project key, the prompt will **only work on domains you have whitelisted** through the [Markprompt dashboard](https://markprompt.com).
### Local development
When developing locally, for instance on localhost, use the development test key instead. This allows you to access the API from a non-whitelisted domain. For that reason, **make sure to keep this key private**.
## Starter Template
For a fully working setup based on Next.js + Tailwind, check out the [Markprompt starter template](https://github.com/motifland/markprompt-starter-template).
For a working setup based on Next.js + Tailwind, check out the [Markprompt starter template](https://github.com/motifland/markprompt-starter-template).

@@ -96,0 +54,0 @@ ## Community

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc