From 79eb6fe55fc2d1e3d8866a3a71213722c7a5dc7c Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Mon, 26 Feb 2024 19:21:45 +0200 Subject: [PATCH 01/27] when pin is hovered change color --- src/arduino-mega-element.stories.ts | 19 ++++++++++-------- src/arduino-mega-element.ts | 3 ++- src/utils/show-pins-element.ts | 30 +++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/arduino-mega-element.stories.ts b/src/arduino-mega-element.stories.ts index 4a24ecf..566f517 100644 --- a/src/arduino-mega-element.stories.ts +++ b/src/arduino-mega-element.stories.ts @@ -3,6 +3,7 @@ import { storiesOf } from '@storybook/web-components'; import { html } from 'lit'; import './arduino-mega-element'; import { action } from '@storybook/addon-actions'; +import './utils/show-pins-element'; storiesOf('Arduino Mega', module) .addParameters({ component: 'wokwi-arduino-mega' }) @@ -10,13 +11,15 @@ storiesOf('Arduino Mega', module) .add( 'Mega', () => html` - + + + ` ); diff --git a/src/arduino-mega-element.ts b/src/arduino-mega-element.ts index 9a8d2af..4037794 100644 --- a/src/arduino-mega-element.ts +++ b/src/arduino-mega-element.ts @@ -11,9 +11,10 @@ export class ArduinoMegaElement extends LitElement { @property() ledTX = false; @property() ledPower = false; @property() resetPressed = false; + // i need to watch for element pin changes @query('#reset-button') resetButton!: SVGCircleElement; - readonly pinInfo: ElementPin[] = [ + pinInfo: ElementPin[] = [ { name: 'SCL', x: 90, y: 9, signals: [i2c('SCL')] }, { name: 'SDA', x: 100, y: 9, signals: [i2c('SDA')] }, { name: 'AREF', x: 109, y: 9, signals: [] }, diff --git a/src/utils/show-pins-element.ts b/src/utils/show-pins-element.ts index b444fa7..88174ab 100644 --- a/src/utils/show-pins-element.ts +++ b/src/utils/show-pins-element.ts @@ -27,9 +27,10 @@ export interface ElementWithPinInfo extends Element { */ @customElement('wokwi-show-pins') export class ShowPinsElement extends LitElement { - @property() pinColor = 'red'; + @property() pinColor = 'black'; @query('#content') elementSlot!: HTMLSlotElement; + activePinIndex = -1; previousSlotChild?: ElementWithPinInfo; get slotChild() { @@ -50,15 +51,36 @@ export class ShowPinsElement extends LitElement { this.requestUpdate(); } + handleMouseOver(index: number) { + if (index !== this.activePinIndex) { + this.activePinIndex = index; + this.requestUpdate(); + } + } + handleMouseOut() { + this.activePinIndex = -1; // Reset active pin to none + this.requestUpdate(); + } + render() { const pinInfo = this.slotChild?.pinInfo ?? []; const { pinColor } = this; return html`
this.handleSlotChange()}> - - + ${pinInfo.map( - (pin) => svg`${pin.name}` + (pin, idx) => + svg` console.log(pin)} + >${pin.name}` )}
`; From b39a9d61e0be7391aa78bde59852dfaef948307a Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Mon, 26 Feb 2024 21:04:15 +0200 Subject: [PATCH 02/27] add small breadboard and select option --- src/assets/SmallBreadboard.svg | 1 + src/breadboard-element.stories.ts | 28 +++ src/breadboard-element.ts | 326 ++++++++++++++++++++++++++++++ src/index.ts | 1 + src/react-types.ts | 2 + src/utils/show-pins-element.ts | 27 ++- 6 files changed, 376 insertions(+), 9 deletions(-) create mode 100644 src/assets/SmallBreadboard.svg create mode 100644 src/breadboard-element.stories.ts create mode 100644 src/breadboard-element.ts diff --git a/src/assets/SmallBreadboard.svg b/src/assets/SmallBreadboard.svg new file mode 100644 index 0000000..f8b7718 --- /dev/null +++ b/src/assets/SmallBreadboard.svg @@ -0,0 +1 @@ +
5
5
10
10
15
15
19
19
0
0
Text is not SVG - cannot display
\ No newline at end of file diff --git a/src/breadboard-element.stories.ts b/src/breadboard-element.stories.ts new file mode 100644 index 0000000..d6bbbd5 --- /dev/null +++ b/src/breadboard-element.stories.ts @@ -0,0 +1,28 @@ +import { html } from 'lit'; +import './breadboard-element'; + +export default { + title: 'Breadboard', + component: 'wokwi-breadboard', + argTypes: { + type: { + control: { + type: 'select', + options: ['mini', 'full'], + }, + }, + }, + args: { + type: 'full', + }, +}; + +const Template = ({ type }) => html` + +`; + +export const Default = Template.bind({}); +Default.args = { value: 5 }; + +export const Large = Template.bind({}); +Large.args = { value: 10 }; diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts new file mode 100644 index 0000000..a3b9caa --- /dev/null +++ b/src/breadboard-element.ts @@ -0,0 +1,326 @@ +import { html, LitElement, svg } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { ElementPin } from './pin'; + +@customElement('wokwi-breadboard') +export class BreadboardElement extends LitElement { + @property() value = 0; + + // colums A-I and rows 0-19 + pinInfo: ElementPin[] = []; + + constructPins() { + // actually first A-E and then padding and then F-J + for (let col = 0; col < 5; col++) { + for (let row = 0; row < 20; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(65 + col)}${row}`, + x: 12.8 + col * 18.2, + y: 31 + row * 18.32, + } as ElementPin); + } + } + + for (let col = 0; col < 5; col++) { + for (let row = 0; row < 20; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(70 + col)}${row}`, + x: 141 + col * 18.2, + y: 31 + row * 18.35, + } as ElementPin); + } + } + } + + firstUpdated() { + this.constructPins(); + } + + render() { + const { value } = this; + // svg is coming from assets folder + return html` + + + + + + + + + + + + +
+
+
+ 5 +
+
+
+ > + + 5 + +
+
+ + + +
+
+
+ 10 +
+
+
+ + 10 + +
+
+ + + +
+
+
+ 15 +
+
+
+ + 15 + +
+
+ + + +
+
+
+ 19 +
+
+
+ + 19 + +
+
+ + + +
+
+
+ 0 +
+
+
+ + 0 + +
+
+
+ + + + + Text is not SVG - cannot display + + + +
+ `; + } +} diff --git a/src/index.ts b/src/index.ts index 386fcbe..d6a485a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -51,3 +51,4 @@ export { StepperMotorElement } from './stepper-motor-element'; export { HX711Element } from './hx711-element'; export { KS2EMDC5Element } from './ks2e-m-dc5-element'; export { BiaxialStepperElement } from './biaxial-stepper-element'; +export { BreadboardElement } from './breadboard-element'; diff --git a/src/react-types.ts b/src/react-types.ts index 0316ea9..d72f015 100644 --- a/src/react-types.ts +++ b/src/react-types.ts @@ -51,6 +51,7 @@ import { HX711Element } from './hx711-element'; import { KS2EMDC5Element } from './ks2e-m-dc5-element'; import { BiaxialStepperElement } from './biaxial-stepper-element'; import type React from 'react'; +import { BreadboardElement } from './breadboard-element'; type WokwiElement = Partial & React.ClassAttributes; @@ -106,6 +107,7 @@ declare global { 'wokwi-hx711': WokwiElement; 'wokwi-ks2e-m-dc5': WokwiElement; 'wokwi-biaxial-stepper': WokwiElement; + 'wokwi-breadboard': WokwiElement; } } } diff --git a/src/utils/show-pins-element.ts b/src/utils/show-pins-element.ts index 88174ab..788435f 100644 --- a/src/utils/show-pins-element.ts +++ b/src/utils/show-pins-element.ts @@ -1,4 +1,4 @@ -import { html, LitElement, svg } from 'lit'; +import { html, LitElement, PropertyPart, svg } from 'lit'; import { customElement, property, query } from 'lit/decorators.js'; import { ElementPin } from '../pin'; @@ -28,6 +28,9 @@ export interface ElementWithPinInfo extends Element { @customElement('wokwi-show-pins') export class ShowPinsElement extends LitElement { @property() pinColor = 'black'; + // need to add properties that are functions that do something with the pins (like a callback), mouseover, click, etc. + // the plan is to use this in another project where im going to write a function that sets to the state that the pin is clicked + @query('#content') elementSlot!: HTMLSlotElement; activePinIndex = -1; @@ -51,16 +54,21 @@ export class ShowPinsElement extends LitElement { this.requestUpdate(); } - handleMouseOver(index: number) { - if (index !== this.activePinIndex) { - this.activePinIndex = index; + handleMouseOver({ pin, idx }: { pin: ElementPin; idx: number }) { + if (idx !== this.activePinIndex) { + this.dispatchEvent(new CustomEvent('pin-mouseover', { detail: { pin, idx } })); + this.activePinIndex = idx; this.requestUpdate(); } } - handleMouseOut() { - this.activePinIndex = -1; // Reset active pin to none + handleMouseOut({ pin, idx }: { pin: ElementPin; idx: number }) { + this.activePinIndex = -1; + this.dispatchEvent(new CustomEvent('pin-mouseout', { detail: { pin, index: idx } })); this.requestUpdate(); } + handlePinClick({ pin, idx }: { pin: ElementPin; idx: number }) { + this.dispatchEvent(new CustomEvent('pin-click', { detail: { pin, index: idx } })); + } render() { const pinInfo = this.slotChild?.pinInfo ?? []; @@ -73,13 +81,14 @@ export class ShowPinsElement extends LitElement { svg` console.log(pin)} + @mouseover=${this.handleMouseOver.bind(this, { pin, idx })} + @mouseout=${this.handleMouseOut.bind(this, { pin, idx })} + @click=${this.handlePinClick.bind(this, { pin, idx })} >${pin.name}` )} From b7b38bbac12ddf89eb1423896c88c012f78327c3 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 27 Feb 2024 20:49:15 +0200 Subject: [PATCH 03/27] finish normal breadboard pin mappings --- src/breadboard-element.stories.ts | 12 +- src/breadboard-element.ts | 1319 +++++++++++++++++++++++------ 2 files changed, 1067 insertions(+), 264 deletions(-) diff --git a/src/breadboard-element.stories.ts b/src/breadboard-element.stories.ts index d6bbbd5..b420c75 100644 --- a/src/breadboard-element.stories.ts +++ b/src/breadboard-element.stories.ts @@ -8,12 +8,12 @@ export default { type: { control: { type: 'select', - options: ['mini', 'full'], + options: ['small', 'normal'], }, }, }, args: { - type: 'full', + type: 'normal', }, }; @@ -21,8 +21,8 @@ const Template = ({ type }) => html` `; -export const Default = Template.bind({}); -Default.args = { value: 5 }; +export const Small = Template.bind({}); +Small.args = { type: 'small' }; -export const Large = Template.bind({}); -Large.args = { value: 10 }; +export const Normal = Template.bind({}); +Normal.args = { type: 'normal' }; diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index a3b9caa..734504b 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -4,13 +4,12 @@ import { ElementPin } from './pin'; @customElement('wokwi-breadboard') export class BreadboardElement extends LitElement { - @property() value = 0; + @property() type: 'small' | 'normal' = 'small'; // colums A-I and rows 0-19 pinInfo: ElementPin[] = []; - constructPins() { - // actually first A-E and then padding and then F-J + constructSmallPins() { for (let col = 0; col < 5; col++) { for (let row = 0; row < 20; row++) { this.pinInfo.push({ @@ -32,295 +31,1099 @@ export class BreadboardElement extends LitElement { } } + constructNormalPins() { + // 2 colums of 25 rows with vertical gap between each 5 rows + // then A-E and rows 0-29; padding; then F-J and rows 0-29 + // 2 colums of 25 rows with vertical gap between each 5 rows + + for (let col = 0; col < 2; col++) { + let startY = 38; + for (let gaps = 0; gaps < 5; gaps++) { + for (let row = 0; row < 5; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(65 + col)}${row}`, + x: 26.6 + col * 18.2, + y: startY + row * 15.2, + } as ElementPin); + } + let addon = gaps === 2 ? 24.7 : gaps === 3 ? 21.7 : 15.5; + startY += 5 * 15.2 + addon; + } + } + + for (let col = 0; col < 5; col++) { + for (let row = 0; row < 30; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(70 + col)}${row}`, + x: 72.3 + col * 15.3, + y: 38 + row * 15.25, + } as ElementPin); + } + } + + for (let col = 0; col < 5; col++) { + for (let row = 0; row < 30; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(70 + col)}${row}`, + x: 179 + col * 15.3, + y: 38 + row * 15.25, + } as ElementPin); + } + } + + for (let col = 0; col < 2; col++) { + let startY = 38; + for (let gaps = 0; gaps < 5; gaps++) { + for (let row = 0; row < 5; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(65 + col)}${row}`, + x: 273.5 + col * 18.2, + y: startY + row * 15.2, + } as ElementPin); + } + let addon = gaps === 2 ? 24.7 : gaps === 3 ? 21.7 : 15.5; + startY += 5 * 15.2 + addon; + } + } + } + firstUpdated() { - this.constructPins(); + const { type } = this; + + if (type === 'small') { + this.constructSmallPins(); + } else { + this.constructNormalPins(); + } } render() { - const { value } = this; + const { type, pinInfo } = this; // svg is coming from assets folder - return html` - - - + return type === 'normal' + ? html` + + + + + + - - - - - - - - -
+ + + + +
+
+
+ 0 +
+
+
+ -
+ + + + + +
- 5 +
+ 5 +
-
-
- > - - 5 - -
-
- - - -
+ -
+ + + + + +
- 10 +
+ 10 +
-
-
- - 10 - - - - - - -
-
+ 10 + + + + + + +
- 15 +
+ 15 +
-
-
- - 15 - - - - - - -
-
+ 15 + + + + + + +
- 19 +
+ 20 +
-
-
- - 19 - - - - - - -
+ + 20 + + + + + + +
+
+
+ 25 +
+
+
+ + 25 + +
+
+ + + +
+
+
+ 29 +
+
+
+ + 29 + +
+
+ + + +
+
+
+ l +
+
+
+ + l + +
+
+ + + +
+
+
+ r +
+
+
+ + r + +
+
+ + + +
+
+
+ 0 +
+
+
+ + 0 + +
+
+ + + +
+
+
+ 5 +
+
+
+ + 5 + +
+
+ + + +
+
+
+ 10 +
+
+
+ -
+ + + + + +
+
+
+ 15 +
+
+
+ + 15 + +
+
+ + + +
+
+
+ 20 +
+
+
+ + 20 + +
+
+ + + +
- 0 +
+ 24 +
-
-
+ + 24 + +
+
+ + + + + + Text is not SVG - cannot display + + + + ` + : html` + + + - + + + + + + + + +
+
+
+ 5 +
+
+
+ > + + 5 + +
+
+ + + +
+
+
+ 10 +
+
+
+ + 10 + +
+
+ + + +
+
+
+ 15 +
+
+
+ + 15 + +
+
+ + + +
+
+
+ 19 +
+
+
+ + 19 + +
+
+ + + +
+
+
+ 0 +
+
+
+ + 0 + +
+
+
+ + + - 0 - + + Text is not SVG - cannot display + + - - - - - - - Text is not SVG - cannot display - - - -
- `; + + `; } } From 76df9494d1ecebc5b6aec83308564fa5203c957e Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 27 Feb 2024 21:47:29 +0200 Subject: [PATCH 04/27] change author --- package.json | 6 +++--- src/utils/show-pins-element.ts | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 57d1578..bf2bdfb 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { - "name": "@wokwi/elements", + "name": "@b.borisov/cu-elements", "version": "1.4.10", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", - "repository": "https://github.com/wokwi/wokwi-elements", - "author": "Uri Shaked ", + "repository": "https://github.com/Pupe6/wokwi-elements", + "author": "Borislav Borisov ", "license": "MIT", "files": [ "dist" diff --git a/src/utils/show-pins-element.ts b/src/utils/show-pins-element.ts index 788435f..ec02231 100644 --- a/src/utils/show-pins-element.ts +++ b/src/utils/show-pins-element.ts @@ -67,6 +67,7 @@ export class ShowPinsElement extends LitElement { this.requestUpdate(); } handlePinClick({ pin, idx }: { pin: ElementPin; idx: number }) { + console.log('pin clicked', pin, idx); this.dispatchEvent(new CustomEvent('pin-click', { detail: { pin, index: idx } })); } From 09b1712897684deecae286723937915b61093f87 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Wed, 28 Feb 2024 18:34:30 +0200 Subject: [PATCH 05/27] modify pin width, height, radius and type --- src/arduino-mega-element.stories.ts | 2 +- src/breadboard-element.stories.ts | 2 +- src/utils/show-pins-element.ts | 37 +++++++++++++++++++++++------ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/arduino-mega-element.stories.ts b/src/arduino-mega-element.stories.ts index 566f517..bc7c4d3 100644 --- a/src/arduino-mega-element.stories.ts +++ b/src/arduino-mega-element.stories.ts @@ -11,7 +11,7 @@ storiesOf('Arduino Mega', module) .add( 'Mega', () => html` - + html` +const Template = ({ type }) => html` `; diff --git a/src/utils/show-pins-element.ts b/src/utils/show-pins-element.ts index ec02231..2e0a08a 100644 --- a/src/utils/show-pins-element.ts +++ b/src/utils/show-pins-element.ts @@ -25,9 +25,18 @@ export interface ElementWithPinInfo extends Element { * `; * ``` */ + +enum PinType { + Circle = 'circle', + Rect = 'rect', +} @customElement('wokwi-show-pins') export class ShowPinsElement extends LitElement { @property() pinColor = 'black'; + @property() pinType: PinType = PinType.Circle; + @property() pinWidth = 5; + @property() pinHeight = 5; + @property() pinRadius = 2.5; // need to add properties that are functions that do something with the pins (like a callback), mouseover, click, etc. // the plan is to use this in another project where im going to write a function that sets to the state that the pin is clicked @@ -73,24 +82,38 @@ export class ShowPinsElement extends LitElement { render() { const pinInfo = this.slotChild?.pinInfo ?? []; - const { pinColor } = this; + const { pinColor, pinType, pinWidth, pinHeight, pinRadius } = this; return html`
this.handleSlotChange()}> - ${pinInfo.map( - (pin, idx) => - svg` + pinType === PinType.Rect + ? svg`${pin.name}` + >${pin.name} + ` + : svg` + ${pin.name} + ` )}
`; From cd2b0c7c802c60347a7323df17c65335969304a5 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Wed, 28 Feb 2024 19:47:26 +0200 Subject: [PATCH 06/27] pins are visible in actual projects --- src/arduino-mega-element.ts | 491 ++++----- src/breadboard-element.ts | 1934 ++++++++++++++++++----------------- 2 files changed, 1219 insertions(+), 1206 deletions(-) diff --git a/src/arduino-mega-element.ts b/src/arduino-mega-element.ts index 4037794..dd0c937 100644 --- a/src/arduino-mega-element.ts +++ b/src/arduino-mega-element.ts @@ -3,7 +3,7 @@ import { customElement, property, query } from 'lit/decorators.js'; import { pinsFemalePattern } from './patterns/pins-female'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; - +import './utils/show-pins-element'; @customElement('wokwi-arduino-mega') export class ArduinoMegaElement extends LitElement { @property() led13 = false; @@ -120,269 +120,276 @@ export class ArduinoMegaElement extends LitElement { render() { const { ledPower, led13, ledRX, ledTX } = this; - return html` - - - - - - - - - - - - - ${pinsFemalePattern} - - - - - - + return; + html` + + + + + + + + - - + + + - - - - - - - - - - this.down()} - @touchstart=${() => this.down()} - @mouseup=${() => this.up()} - @mouseleave=${() => this.leave()} - @touchend=${() => this.leave()} - @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} - @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} - /> + ${pinsFemalePattern} - - - - - - - - - - - + + + + + - - + - - - - - - + - - + + + + + + + this.down()} + @touchstart=${() => this.down()} + @mouseup=${() => this.up()} + @mouseleave=${() => this.leave()} + @touchend=${() => this.leave()} + @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} + @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} /> - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - ${ledPower && - svg``} - + + - - PWR - + + + + - - - ${led13 && - svg``} - + + + + ${ledPower && + svg``} + - - - ${ledTX && - svg``} - + + PWR + - - - ${ledRX && - svg``} - + + + ${led13 && + svg``} + - - L - TX - RX -   - + + + ${ledTX && + svg``} + - - - - PWM - + + + ${ledRX && + svg``} + - - - COMMUNICATION - + + L + TX + RX +   + - - AREF - GND - 13 - 12 - 11 - 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - TX→ 1 - RX← 0 - TX3 14 - RX3 15 - TX2 16 - RX2 17 - TX1 18 - RX1 19 - SDA 20 - SCL 21 -   - + + + + PWM + + + + + COMMUNICATION + + + + AREF + GND + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + TX→ 1 + RX← 0 + TX3 14 + RX3 15 + TX2 16 + RX2 17 + TX1 18 + RX1 19 + SDA 20 + SCL 21 +   + - - - - POWER - ANALOG IN - - - IOREF - RESET - 3.3V - 5V - GND - GND - Vin - A0 - A1 - A2 - A3 - A4 - A5 - A6 - A7 - A8 - A9 - A10 - A11 - A12 - A13 - A14 - A15 -   - + + + + POWER + ANALOG IN + + + IOREF + RESET + 3.3V + 5V + GND + GND + Vin + A0 + A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 +   + - - - Arduino MEGA - - + + + Arduino MEGA + + +
`; } private down() { diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index 734504b..b956fd3 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -1,7 +1,7 @@ import { html, LitElement, svg } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin } from './pin'; - +import './utils/show-pins-element'; @customElement('wokwi-breadboard') export class BreadboardElement extends LitElement { @property() type: 'small' | 'normal' = 'small'; @@ -101,1029 +101,1035 @@ export class BreadboardElement extends LitElement { const { type, pinInfo } = this; // svg is coming from assets folder return type === 'normal' - ? html` - - + - - - - - - - - - - -
-
-
- 0 -
-
-
+ - - 0 - -
-
- - - -
-
+ + + + + + + + + +
+
+
+ 0 +
+
+
+ -
+ + + + + +
- 5 -
-
-
- - 5 - - - - - - -
-
+
+ 5 +
+
+
-
+ 5 + + + + + + +
- 10 -
-
-
- - 10 - -
-
- - - -
-
+
+ 10 +
+
+
+ -
+ + + + + +
- 15 -
-
-
- - 15 - -
-
- - - -
-
+
+ 15 +
+
+
+ -
+ + + + + +
- 20 -
-
-
- - 20 - -
-
- - - -
-
+
+ 20 +
+
+
+ -
+ + + + + +
- 25 -
-
-
- - 25 - -
-
- - - -
-
+
+ 25 +
+
+
-
+ 25 + + + + + + +
- 29 -
-
-
- - 29 - -
-
- - - -
-
+
+ 29 +
+
+
+ -
+ + + + + +
- l -
-
-
- - l - -
-
- - - -
-
+
+ l +
+
+
+ -
+ + + + + +
- r -
-
- - - r - - - - - - -
-
+
+ r +
+
+
-
+ r + + + + + + +
- 0 -
-
- - - 0 - -
-
- - - -
-
+
+ 0 +
+
+
-
+ 0 + + + + + + +
- 5 -
-
- - - 5 - -
-
- - - -
-
+
+ 5 +
+
+
+ -
+ + + + + +
- 10 -
-
- - - 10 - -
-
- - - -
-
+
+ 10 +
+
+
+ -
+ + + + + +
- 15 -
-
- - - 15 - -
-
- - - -
-
+
+ 15 +
+
+
-
+ 15 + + + + + + +
- 20 -
-
- - - 20 - -
-
- - - -
-
+
+ 20 +
+
+
+ -
+ + + + + +
- 24 -
-
- - +
+ 24 +
+ + + + 24 + +
+
+ + + + - 24 - + + Text is not SVG - cannot display + + - - - - - - - Text is not SVG - cannot display - - - - ` + + + ` : html` - - - + + + + + + + + - - - - - - - - -
-
+ + + +
- 5 +
+ 5 +
-
-
- > - - 5 - - - - - - -
+ > + -
+ + + + + +
- 10 +
+ 10 +
-
-
- - 10 - - - - - - -
+ -
+ + + + + +
- 15 +
+ 15 +
-
-
- - 15 - - - - - - -
-
+ 15 + + + + + + +
- 19 +
+ 19 +
-
-
- - 19 - - - - - - -
+ -
+ + + + + +
- 0 +
+ 0 +
-
-
- - 0 - - +
+ + 0 + +
+
- - - - - - Text is not SVG - cannot display - - - - + + + + + Text is not SVG - cannot display + + + + + `; } } From fc3d7bc1b28b5b405d477f4cfdec02905edb73ac Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Wed, 28 Feb 2024 19:51:59 +0200 Subject: [PATCH 07/27] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bf2bdfb..6455695 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.10", + "version": "1.4.11", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From f4b6f0752cd301c14eb384a09df382e76ee45026 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Wed, 28 Feb 2024 20:40:17 +0200 Subject: [PATCH 08/27] export show pins as element --- package.json | 2 +- src/arduino-mega-element.ts | 489 +++++----- src/breadboard-element.ts | 1840 +++++++++++++++++------------------ src/index.ts | 1 + src/react-types.ts | 3 +- 5 files changed, 1163 insertions(+), 1172 deletions(-) diff --git a/package.json b/package.json index 6455695..e95ebe3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.11", + "version": "1.4.12", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", diff --git a/src/arduino-mega-element.ts b/src/arduino-mega-element.ts index dd0c937..6b9cc71 100644 --- a/src/arduino-mega-element.ts +++ b/src/arduino-mega-element.ts @@ -120,276 +120,269 @@ export class ArduinoMegaElement extends LitElement { render() { const { ledPower, led13, ledRX, ledTX } = this; - return; - html` - - - - - - - - + return html` + + + + + + + - - - + + + - ${pinsFemalePattern} + ${pinsFemalePattern} - - - - - + + + + + - - + + - - - - - - - - - - this.down()} - @touchstart=${() => this.down()} - @mouseup=${() => this.up()} - @mouseleave=${() => this.leave()} - @touchend=${() => this.leave()} - @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} - @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} - /> + + + + + + + + + + this.down()} + @touchstart=${() => this.down()} + @mouseup=${() => this.up()} + @mouseleave=${() => this.leave()} + @touchend=${() => this.leave()} + @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} + @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} + /> - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - ${ledPower && - svg``} - + + + + ${ledPower && + svg``} + - - PWR - + + PWR + - - - ${led13 && - svg``} - + + + ${led13 && + svg``} + - - - ${ledTX && - svg``} - + + + ${ledTX && + svg``} + - - - ${ledRX && - svg``} - + + + ${ledRX && + svg``} + - - L - TX - RX -   - + + L + TX + RX +   + - - - - PWM - + + + + PWM + - - - COMMUNICATION - + + + COMMUNICATION + - - AREF - GND - 13 - 12 - 11 - 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - TX→ 1 - RX← 0 - TX3 14 - RX3 15 - TX2 16 - RX2 17 - TX1 18 - RX1 19 - SDA 20 - SCL 21 -   - + + AREF + GND + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + TX→ 1 + RX← 0 + TX3 14 + RX3 15 + TX2 16 + RX2 17 + TX1 18 + RX1 19 + SDA 20 + SCL 21 +   + - - - - POWER - ANALOG IN - - - IOREF - RESET - 3.3V - 5V - GND - GND - Vin - A0 - A1 - A2 - A3 - A4 - A5 - A6 - A7 - A8 - A9 - A10 - A11 - A12 - A13 - A14 - A15 -   - + + + + POWER + ANALOG IN + + + IOREF + RESET + 3.3V + 5V + GND + GND + Vin + A0 + A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 +   + - - - Arduino MEGA - - - + + + Arduino MEGA + + `; } private down() { diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index b956fd3..bf5a9d0 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -102,1034 +102,1030 @@ export class BreadboardElement extends LitElement { // svg is coming from assets folder return type === 'normal' ? html` - - - - - - - - + + + - - - - - -
+ + + + + + + + +
+
-
- 0 -
+ 0
-
- +
+ + 0 + +
+
+ + + +
- 0 - - - - - - -
-
- 5 -
+ 5
-
- +
+ + 5 + +
+
+ + + +
- 5 - - - - - - -
-
- 10 -
+ 10
-
- +
+ + 10 + +
+
+ + + +
- 10 - - - - - - -
-
- 15 -
+ 15
-
- +
+ + 15 + +
+
+ + + +
- 15 - - - - - - -
-
- 20 -
+ 20
-
- +
+ + 20 + +
+
+ + + +
- 20 - - - - - - -
-
- 25 -
+ 25
-
- +
+ + 25 + +
+
+ + + +
- 25 - - - - - - -
-
- 29 -
+ 29
-
- +
+ + 29 + +
+
+ + + +
- 29 - - - - - - -
-
- l -
+ l
-
- +
+ + l + +
+
+ + + +
- l - - - - - - -
-
- r -
+ r
-
- +
+ + r + +
+
+ + + +
- r - - - - - - -
-
- 0 -
+ 0
-
- +
+ + 0 + +
+
+ + + +
- 0 - - - - - - -
-
- 5 -
+ 5
-
- +
+ + 5 + +
+
+ + + +
- 5 - - - - - - -
-
- 10 -
+ 10
-
- +
+ + 10 + +
+
+ + + +
- 10 - - - - - - -
-
- 15 -
+ 15
-
- +
+ + 15 + +
+
+ + + +
- 15 - - - - - - -
-
- 20 -
+ 20
-
- +
+ + 20 + +
+
+ + + +
- 20 - - - - - - -
-
- 24 -
+ 24
-
- - 24 - -
-
- - - - - - Text is not SVG - cannot display +
+
+ + 24 - -
-
-
+ + + + + + + + Text is not SVG - cannot display + + + + ` : html` - - - - - - - - - - + + + - - -
+ + + + + + + +
+
-
- 5 -
+ 5
-
- > - +
+ > + + 5 + +
+
+ + + +
- 5 - - - - - - -
-
- 10 -
+ 10
-
- +
+ + 10 + +
+
+ + + +
- 10 - - - - - - -
-
- 15 -
+ 15
-
- +
+ + 15 + +
+
+ + + +
- 15 - - - - - - -
-
- 19 -
+ 19
-
- +
+ + 19 + +
+
+ + + +
- 19 - - - - - - -
-
- 0 -
+ 0
-
- - 0 - -
-
- - - - - - Text is not SVG - cannot display +
+
+ + 0 - -
-
-
+ + + + + + + + Text is not SVG - cannot display + + + + `; } } diff --git a/src/index.ts b/src/index.ts index d6a485a..f83c1a4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -52,3 +52,4 @@ export { HX711Element } from './hx711-element'; export { KS2EMDC5Element } from './ks2e-m-dc5-element'; export { BiaxialStepperElement } from './biaxial-stepper-element'; export { BreadboardElement } from './breadboard-element'; +export { ShowPinsElement } from './utils/show-pins-element'; diff --git a/src/react-types.ts b/src/react-types.ts index d72f015..ba7ebba 100644 --- a/src/react-types.ts +++ b/src/react-types.ts @@ -52,9 +52,9 @@ import { KS2EMDC5Element } from './ks2e-m-dc5-element'; import { BiaxialStepperElement } from './biaxial-stepper-element'; import type React from 'react'; import { BreadboardElement } from './breadboard-element'; +import { ShowPinsElement } from './utils/show-pins-element'; type WokwiElement = Partial & React.ClassAttributes; - declare global { namespace JSX { interface IntrinsicElements { @@ -108,6 +108,7 @@ declare global { 'wokwi-ks2e-m-dc5': WokwiElement; 'wokwi-biaxial-stepper': WokwiElement; 'wokwi-breadboard': WokwiElement; + 'wokwi-show-pins': WokwiElement; } } } From caeffd42ebb150164a7983053b31a1090d76adf1 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Wed, 28 Feb 2024 21:01:57 +0200 Subject: [PATCH 09/27] add show pin as element --- .storybook/preview.js | 2 -- src/arduino-mega-element.stories.ts | 19 +++++++--------- src/arduino-mega-element.ts | 1 - src/breadboard-element.stories.ts | 4 +--- src/breadboard-element.ts | 1 - src/index.ts | 2 +- src/react-types.ts | 2 +- src/show-pins-element.stories.ts | 34 ++++++++++++++++++++++++++++ src/{utils => }/show-pins-element.ts | 3 ++- 9 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 src/show-pins-element.stories.ts rename src/{utils => }/show-pins-element.ts (99%) diff --git a/.storybook/preview.js b/.storybook/preview.js index 024d3cc..6a9360b 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -5,7 +5,5 @@ export const parameters = { import { setCustomElements } from '@storybook/web-components'; import customElements from '../custom-elements.json'; -import '../src/utils/show-pins-element'; - // Configure Storybook Docs Addon for Web Components setCustomElements(customElements); diff --git a/src/arduino-mega-element.stories.ts b/src/arduino-mega-element.stories.ts index bc7c4d3..4a24ecf 100644 --- a/src/arduino-mega-element.stories.ts +++ b/src/arduino-mega-element.stories.ts @@ -3,7 +3,6 @@ import { storiesOf } from '@storybook/web-components'; import { html } from 'lit'; import './arduino-mega-element'; import { action } from '@storybook/addon-actions'; -import './utils/show-pins-element'; storiesOf('Arduino Mega', module) .addParameters({ component: 'wokwi-arduino-mega' }) @@ -11,15 +10,13 @@ storiesOf('Arduino Mega', module) .add( 'Mega', () => html` - - - + ` ); diff --git a/src/arduino-mega-element.ts b/src/arduino-mega-element.ts index 6b9cc71..b7cd36e 100644 --- a/src/arduino-mega-element.ts +++ b/src/arduino-mega-element.ts @@ -3,7 +3,6 @@ import { customElement, property, query } from 'lit/decorators.js'; import { pinsFemalePattern } from './patterns/pins-female'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; -import './utils/show-pins-element'; @customElement('wokwi-arduino-mega') export class ArduinoMegaElement extends LitElement { @property() led13 = false; diff --git a/src/breadboard-element.stories.ts b/src/breadboard-element.stories.ts index 2e114e2..58d81f2 100644 --- a/src/breadboard-element.stories.ts +++ b/src/breadboard-element.stories.ts @@ -17,9 +17,7 @@ export default { }, }; -const Template = ({ type }) => html` - -`; +const Template = ({ type }) => html` `; export const Small = Template.bind({}); Small.args = { type: 'small' }; diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index bf5a9d0..5ade187 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -1,7 +1,6 @@ import { html, LitElement, svg } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin } from './pin'; -import './utils/show-pins-element'; @customElement('wokwi-breadboard') export class BreadboardElement extends LitElement { @property() type: 'small' | 'normal' = 'small'; diff --git a/src/index.ts b/src/index.ts index f83c1a4..b00d139 100644 --- a/src/index.ts +++ b/src/index.ts @@ -52,4 +52,4 @@ export { HX711Element } from './hx711-element'; export { KS2EMDC5Element } from './ks2e-m-dc5-element'; export { BiaxialStepperElement } from './biaxial-stepper-element'; export { BreadboardElement } from './breadboard-element'; -export { ShowPinsElement } from './utils/show-pins-element'; +export { ShowPinsElement } from './show-pins-element'; diff --git a/src/react-types.ts b/src/react-types.ts index ba7ebba..86932ad 100644 --- a/src/react-types.ts +++ b/src/react-types.ts @@ -52,7 +52,7 @@ import { KS2EMDC5Element } from './ks2e-m-dc5-element'; import { BiaxialStepperElement } from './biaxial-stepper-element'; import type React from 'react'; import { BreadboardElement } from './breadboard-element'; -import { ShowPinsElement } from './utils/show-pins-element'; +import { ShowPinsElement } from './show-pins-element'; type WokwiElement = Partial & React.ClassAttributes; declare global { diff --git a/src/show-pins-element.stories.ts b/src/show-pins-element.stories.ts new file mode 100644 index 0000000..85ba93b --- /dev/null +++ b/src/show-pins-element.stories.ts @@ -0,0 +1,34 @@ +import { html } from 'lit'; +import './show-pins-element'; + +export default { + title: 'Show Pin', + component: 'wokwi-show-pins', + argTypes: { + pinColor: { control: 'color' }, + pinType: { control: { type: 'select', options: ['circle', 'rect'] } }, + pinWidth: { control: 'number' }, + pinHeight: { control: 'number' }, + pinRadius: { control: 'number' }, + }, + args: { + pinColor: 'transparent', + pinType: 'circle', + pinWidth: 5, + pinHeight: 5, + pinRadius: 2.5, + }, +}; + +const Template = ({ pinColor, pinType, pinWidth, pinHeight, pinRadius }) => html` + +`; + +export const Default = Template.bind({}); +Default.args = { pinColor: 'transparent' }; diff --git a/src/utils/show-pins-element.ts b/src/show-pins-element.ts similarity index 99% rename from src/utils/show-pins-element.ts rename to src/show-pins-element.ts index 2e0a08a..d752dc0 100644 --- a/src/utils/show-pins-element.ts +++ b/src/show-pins-element.ts @@ -1,6 +1,6 @@ import { html, LitElement, PropertyPart, svg } from 'lit'; import { customElement, property, query } from 'lit/decorators.js'; -import { ElementPin } from '../pin'; +import { ElementPin } from './pin'; export interface ElementWithPinInfo extends Element { pinInfo?: ElementPin[]; @@ -30,6 +30,7 @@ enum PinType { Circle = 'circle', Rect = 'rect', } + @customElement('wokwi-show-pins') export class ShowPinsElement extends LitElement { @property() pinColor = 'black'; From 487927c60be672fdd1fe72005ea4dedf690a3f43 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Wed, 28 Feb 2024 21:02:40 +0200 Subject: [PATCH 10/27] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e95ebe3..d469a9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.12", + "version": "1.4.13", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From 28dba713346b0dde873167586c58a3a2315b9eee Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Sun, 3 Mar 2024 12:51:55 +0200 Subject: [PATCH 11/27] renake small breadboard --- src/assets/SmallBreadboard.svg | 2 +- src/breadboard-element.stories.ts | 6 +- src/breadboard-element.ts | 1156 ++++++++++++++++++++++------- src/show-pins-element.ts | 7 +- 4 files changed, 879 insertions(+), 292 deletions(-) diff --git a/src/assets/SmallBreadboard.svg b/src/assets/SmallBreadboard.svg index f8b7718..ac5af8d 100644 --- a/src/assets/SmallBreadboard.svg +++ b/src/assets/SmallBreadboard.svg @@ -1 +1 @@ -
5
5
10
10
15
15
19
19
0
0
Text is not SVG - cannot display
\ No newline at end of file +
a
a
b
b
c
c
d
d
e
e
f
f
h
h
g
g
0
0
1
1
2
2
3
3
Text is not SVG - cannot display
\ No newline at end of file diff --git a/src/breadboard-element.stories.ts b/src/breadboard-element.stories.ts index 58d81f2..8dca0d7 100644 --- a/src/breadboard-element.stories.ts +++ b/src/breadboard-element.stories.ts @@ -17,7 +17,11 @@ export default { }, }; -const Template = ({ type }) => html` `; +const Template = ({ type }) => html` + + + +`; export const Small = Template.bind({}); Small.args = { type: 'small' }; diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index 5ade187..b7752d9 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -9,22 +9,22 @@ export class BreadboardElement extends LitElement { pinInfo: ElementPin[] = []; constructSmallPins() { - for (let col = 0; col < 5; col++) { - for (let row = 0; row < 20; row++) { + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 4; row++) { this.pinInfo.push({ name: `${String.fromCharCode(65 + col)}${row}`, - x: 12.8 + col * 18.2, - y: 31 + row * 18.32, + x: 10.3 + col * 17, + y: 26 + row * 17, } as ElementPin); } } - for (let col = 0; col < 5; col++) { - for (let row = 0; row < 20; row++) { + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 4; row++) { this.pinInfo.push({ name: `${String.fromCharCode(70 + col)}${row}`, - x: 141 + col * 18.2, - y: 31 + row * 18.35, + x: 112.7 + col * 17, + y: 26 + row * 17, } as ElementPin); } } @@ -105,57 +105,66 @@ export class BreadboardElement extends LitElement { xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" - width="315px" - height="510px" - viewBox="-0.5 -0.5 637 1021" - content='<mxfile><diagram id="CZv6xJV_rrJ8GXY5pJqV" name="Page-1">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</diagram></mxfile>' + width="192px" + height="225px" + viewBox="-0.5 -0.5 192 225" + content='<mxfile><diagram id="oG0qLGzZM064v2p6Xe1s" name="Page-1">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</diagram></mxfile>' > - + +
- 0 + a
- 0 + a
- 5 + b
- 5 + b
- 10 + c
- 10 + c
- 15 + d
- 15 + d
- 20 + e
- 20 + e
- 25 + f
- 25 + f
- 29 + h
- 29 + h
- l + g
- l + g
- r + 0
- r + 0
- 0 + 1
- 0 + 1
- 5 + 2
- 5 + 2
- 10 + 3
- 10 + 3 +
- 15 + 4
- 15 + 4
- 20 + 5
- 20 + 5
- 24 + 6
- 24 + 6 - - - - - - Text is not SVG - cannot display - - - - - ` - : html` - - - - - - - - + + +
+
+
+ 7 +
+
+
+ + 7 + +
+
- 5 + 8
+ + 8 + + + + + + +
+
+
+ 9 +
+
+
- 5 + 9
+ + +
+
+
+ 11 +
+
+
+ + 11 + +
+
+ + + + + + Text is not SVG - cannot display + + + + + ` + : html` + + + + + + + + + + + +
- 15 + a
- 15 + a
- 19 + b
- 19 + b
- 0 + c
- 0 + c - - - - + + +
+
+
+ d +
+
+
+ + d + +
+
+ + + +
+
+
+ e +
+
+
+ + e + +
+
+ + + +
+
+
+ f +
+
+
+ + f + +
+
+ + + +
+
+
+ h +
+
+
+ + h + +
+
+ + + +
+
+
+ g +
+
+
+ + g + +
+
+ + + +
+
+
+ 0 +
+
+
+ + 0 + +
+
+ + + +
+
+
+ 1 +
+
+
+ + 1 + +
+
+ + + +
+
+
+ 2 +
+
+
+ + 2 + +
+
+ + + +
+
+
+ 3 +
+
+
+ + 3 + +
+
+ +
+ + + diff --git a/src/show-pins-element.ts b/src/show-pins-element.ts index d752dc0..808b6fb 100644 --- a/src/show-pins-element.ts +++ b/src/show-pins-element.ts @@ -38,6 +38,7 @@ export class ShowPinsElement extends LitElement { @property() pinWidth = 5; @property() pinHeight = 5; @property() pinRadius = 2.5; + // need to add properties that are functions that do something with the pins (like a callback), mouseover, click, etc. // the plan is to use this in another project where im going to write a function that sets to the state that the pin is clicked @@ -66,19 +67,19 @@ export class ShowPinsElement extends LitElement { handleMouseOver({ pin, idx }: { pin: ElementPin; idx: number }) { if (idx !== this.activePinIndex) { - this.dispatchEvent(new CustomEvent('pin-mouseover', { detail: { pin, idx } })); + document.dispatchEvent(new CustomEvent('pin-mouseover', { detail: { pin, idx } })); this.activePinIndex = idx; this.requestUpdate(); } } handleMouseOut({ pin, idx }: { pin: ElementPin; idx: number }) { this.activePinIndex = -1; - this.dispatchEvent(new CustomEvent('pin-mouseout', { detail: { pin, index: idx } })); + document.dispatchEvent(new CustomEvent('pin-mouseout', { detail: { pin, index: idx } })); this.requestUpdate(); } handlePinClick({ pin, idx }: { pin: ElementPin; idx: number }) { console.log('pin clicked', pin, idx); - this.dispatchEvent(new CustomEvent('pin-click', { detail: { pin, index: idx } })); + document.dispatchEvent(new CustomEvent('pin-click', { detail: { pin, index: idx } })); } render() { From 54b99f2a840e3d82995a2fc8be2419400154eeee Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Sun, 3 Mar 2024 16:52:04 +0200 Subject: [PATCH 12/27] redesign of the normal breadboard --- src/breadboard-element.ts | 50 +++++++-------------------------------- 1 file changed, 8 insertions(+), 42 deletions(-) diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index b7752d9..08cee51 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -31,59 +31,25 @@ export class BreadboardElement extends LitElement { } constructNormalPins() { - // 2 colums of 25 rows with vertical gap between each 5 rows - // then A-E and rows 0-29; padding; then F-J and rows 0-29 - // 2 colums of 25 rows with vertical gap between each 5 rows - - for (let col = 0; col < 2; col++) { - let startY = 38; - for (let gaps = 0; gaps < 5; gaps++) { - for (let row = 0; row < 5; row++) { - this.pinInfo.push({ - name: `${String.fromCharCode(65 + col)}${row}`, - x: 26.6 + col * 18.2, - y: startY + row * 15.2, - } as ElementPin); - } - let addon = gaps === 2 ? 24.7 : gaps === 3 ? 21.7 : 15.5; - startY += 5 * 15.2 + addon; - } - } - - for (let col = 0; col < 5; col++) { - for (let row = 0; row < 30; row++) { + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 12; row++) { this.pinInfo.push({ name: `${String.fromCharCode(70 + col)}${row}`, - x: 72.3 + col * 15.3, - y: 38 + row * 15.25, + x: 10.3 + col * 17.15, + y: 26 + row * 17.15, } as ElementPin); } } - for (let col = 0; col < 5; col++) { - for (let row = 0; row < 30; row++) { + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 12; row++) { this.pinInfo.push({ name: `${String.fromCharCode(70 + col)}${row}`, - x: 179 + col * 15.3, - y: 38 + row * 15.25, + x: 113 + col * 17.15, + y: 26 + row * 17.15, } as ElementPin); } } - - for (let col = 0; col < 2; col++) { - let startY = 38; - for (let gaps = 0; gaps < 5; gaps++) { - for (let row = 0; row < 5; row++) { - this.pinInfo.push({ - name: `${String.fromCharCode(65 + col)}${row}`, - x: 273.5 + col * 18.2, - y: startY + row * 15.2, - } as ElementPin); - } - let addon = gaps === 2 ? 24.7 : gaps === 3 ? 21.7 : 15.5; - startY += 5 * 15.2 + addon; - } - } } firstUpdated() { From 047f4a9ba6cbdaeb6a037b5a0d3df43b5bafa15e Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Sun, 3 Mar 2024 16:52:27 +0200 Subject: [PATCH 13/27] new pkg version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d469a9a..d825360 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.13", + "version": "1.4.14", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From 9e75d2b478493cf34a32998d6434ba5a71e8a54d Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Sun, 3 Mar 2024 22:09:08 +0200 Subject: [PATCH 14/27] intrinsic elements are now capitalized --- package.json | 2 +- src/breadboard-element.ts | 6 +-- src/react-types.ts | 103 +++++++++++++++++++------------------- 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index d825360..6e60db6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.14", + "version": "1.4.15", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index 08cee51..f437a82 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -22,7 +22,7 @@ export class BreadboardElement extends LitElement { for (let col = 0; col < 4; col++) { for (let row = 0; row < 4; row++) { this.pinInfo.push({ - name: `${String.fromCharCode(70 + col)}${row}`, + name: `${String.fromCharCode(69 + col)}${row}`, x: 112.7 + col * 17, y: 26 + row * 17, } as ElementPin); @@ -34,7 +34,7 @@ export class BreadboardElement extends LitElement { for (let col = 0; col < 4; col++) { for (let row = 0; row < 12; row++) { this.pinInfo.push({ - name: `${String.fromCharCode(70 + col)}${row}`, + name: `${String.fromCharCode(65 + col)}${row}`, x: 10.3 + col * 17.15, y: 26 + row * 17.15, } as ElementPin); @@ -44,7 +44,7 @@ export class BreadboardElement extends LitElement { for (let col = 0; col < 4; col++) { for (let row = 0; row < 12; row++) { this.pinInfo.push({ - name: `${String.fromCharCode(70 + col)}${row}`, + name: `${String.fromCharCode(69 + col)}${row}`, x: 113 + col * 17.15, y: 26 + row * 17.15, } as ElementPin); diff --git a/src/react-types.ts b/src/react-types.ts index 86932ad..1760b95 100644 --- a/src/react-types.ts +++ b/src/react-types.ts @@ -55,60 +55,61 @@ import { BreadboardElement } from './breadboard-element'; import { ShowPinsElement } from './show-pins-element'; type WokwiElement = Partial & React.ClassAttributes; + declare global { namespace JSX { interface IntrinsicElements { - 'wokwi-7segment': WokwiElement; - 'wokwi-arduino-uno': WokwiElement; - 'wokwi-lcd1602': WokwiElement; - 'wokwi-led': WokwiElement; - 'wokwi-neopixel': WokwiElement; - 'wokwi-pushbutton': WokwiElement; - 'wokwi-resistor': WokwiElement; - 'wokwi-membrane-keypad': WokwiElement; - 'wokwi-potentiometer': WokwiElement; - 'wokwi-neopixel-matrix': WokwiElement; - 'wokwi-ssd1306': WokwiElement; - 'wokwi-buzzer': WokwiElement; - 'wokwi-rotary-dialer': WokwiElement; - 'wokwi-servo': WokwiElement; - 'wokwi-dht22': WokwiElement; - 'wokwi-arduino-mega': WokwiElement; - 'wokwi-arduino-nano': WokwiElement; - 'wokwi-ds1307': WokwiElement; - 'wokwi-neopixel-ring': WokwiElement; - 'wokwi-slide-switch': WokwiElement; - 'wokwi-hc-sr04': WokwiElement; - 'wokwi-lcd2004': WokwiElement; - 'wokwi-analog-joystick': WokwiElement; - 'wokwi-slide-potentiometer': WokwiElement; - 'wokwi-ir-receiver': WokwiElement; - 'wokwi-ir-remote': WokwiElement; - 'wokwi-pir-motion-sensor': WokwiElement; - 'wokwi-ntc-temperature-sensor': WokwiElement; - 'wokwi-heart-beat-sensor': WokwiElement; - 'wokwi-tilt-switch': WokwiElement; - 'wokwi-flame-sensor': WokwiElement; - 'wokwi-gas-sensor': WokwiElement; - 'wokwi-franzininho': WokwiElement; - 'wokwi-nano-rp2040-connect': WokwiElement; - 'wokwi-small-sound-sensor': WokwiElement; - 'wokwi-big-sound-sensor': WokwiElement; - 'wokwi-mpu6050': WokwiElement; - 'wokwi-esp32-devkit-v1': WokwiElement; - 'wokwi-ky-040': WokwiElement; - 'wokwi-photoresistor-sensor': WokwiElement; - 'wokwi-rgb-led': WokwiElement; - 'wokwi-ili9341': WokwiElement; - 'wokwi-led-bar-graph': WokwiElement; - 'wokwi-microsd-card': WokwiElement; - 'wokwi-dip-switch-8': WokwiElement; - 'wokwi-stepper-motor': WokwiElement; - 'wokwi-hx711': WokwiElement; - 'wokwi-ks2e-m-dc5': WokwiElement; - 'wokwi-biaxial-stepper': WokwiElement; - 'wokwi-breadboard': WokwiElement; - 'wokwi-show-pins': WokwiElement; + SevenSegment: WokwiElement; + ArduinoUno: WokwiElement; + LCD1602: WokwiElement; + LED: WokwiElement; + NeoPixel: WokwiElement; + Pushbutton: WokwiElement; + Resistor: WokwiElement; + MembraneKeypad: WokwiElement; + Potentiometer: WokwiElement; + NeopixelMatrix: WokwiElement; + SSD1306: WokwiElement; + Buzzer: WokwiElement; + RotaryDialer: WokwiElement; + Servo: WokwiElement; + DHT22: WokwiElement; + ArduinoMega: WokwiElement; + ArduinoNano: WokwiElement; + DS1307: WokwiElement; + LEDRing: WokwiElement; + SlideSwitch: WokwiElement; + HCSR04: WokwiElement; + LCD2004: WokwiElement; + AnalogJoystick: WokwiElement; + SlidePotentiometer: WokwiElement; + IRReceiver: WokwiElement; + IRRemote: WokwiElement; + PIRMotionSensor: WokwiElement; + NTCTemperatureSensor: WokwiElement; + HeartBeatSensor: WokwiElement; + TiltSwitch: WokwiElement; + FlameSensor: WokwiElement; + GasSensor: WokwiElement; + Franzininho: WokwiElement; + NanoRP2040Connect: WokwiElement; + SmallSoundSensor: WokwiElement; + BigSoundSensor: WokwiElement; + MPU6050: WokwiElement; + ESP32DevkitV1: WokwiElement; + KY040: WokwiElement; + PhotoresistorSensor: WokwiElement; + RGBLed: WokwiElement; + ILI9341: WokwiElement; + LedBarGraph: WokwiElement; + MicrosdCard: WokwiElement; + DipSwitch8: WokwiElement; + StepperMotor: WokwiElement; + HX711: WokwiElement; + KS2EMDC5: WokwiElement; + BiaxialStepper: WokwiElement; + Breadboard: WokwiElement; + ShowPins: WokwiElement; } } } From 4b5c86f5a41ad8330a95346045689953570ef6ab Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Sun, 3 Mar 2024 22:11:44 +0200 Subject: [PATCH 15/27] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e60db6..2b7d171 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.15", + "version": "1.4.16", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From 354dc7b721752b857865a333929f5be0ad32b0c6 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Thu, 28 Mar 2024 21:13:00 +0200 Subject: [PATCH 16/27] rename components --- package.json | 2 +- src/arduino-mega-element.stories.ts | 2 +- src/arduino-mega-element.ts | 490 ++++---- src/arduino-nano-element.stories.ts | 6 +- src/arduino-nano-element.ts | 400 +++--- src/arduino-uno-element.stories.ts | 2 +- src/arduino-uno-element.ts | 521 ++++---- src/breadboard-element.stories.ts | 4 +- src/breadboard-element.ts | 1783 ++++++++++++++------------- src/react-types.ts | 5 +- src/rgb-led-element.ts | 2 +- 11 files changed, 1627 insertions(+), 1590 deletions(-) diff --git a/package.json b/package.json index 2b7d171..6a63398 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.16", + "version": "1.4.17", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", diff --git a/src/arduino-mega-element.stories.ts b/src/arduino-mega-element.stories.ts index 4a24ecf..a581b85 100644 --- a/src/arduino-mega-element.stories.ts +++ b/src/arduino-mega-element.stories.ts @@ -5,7 +5,7 @@ import './arduino-mega-element'; import { action } from '@storybook/addon-actions'; storiesOf('Arduino Mega', module) - .addParameters({ component: 'wokwi-arduino-mega' }) + .addParameters({ component: 'ArduinoMegaElement' }) .addDecorator(withKnobs) .add( 'Mega', diff --git a/src/arduino-mega-element.ts b/src/arduino-mega-element.ts index b7cd36e..6b2bc84 100644 --- a/src/arduino-mega-element.ts +++ b/src/arduino-mega-element.ts @@ -3,7 +3,9 @@ import { customElement, property, query } from 'lit/decorators.js'; import { pinsFemalePattern } from './patterns/pins-female'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; -@customElement('wokwi-arduino-mega') + +import './show-pins-element'; +@customElement('ArduinoMegaElement') export class ArduinoMegaElement extends LitElement { @property() led13 = false; @property() ledRX = false; @@ -120,268 +122,274 @@ export class ArduinoMegaElement extends LitElement { render() { const { ledPower, led13, ledRX, ledTX } = this; return html` - - - - - - - - - - - - - ${pinsFemalePattern} - - - - - - + + + + + + + + - - + + + - - - - - - - - - - this.down()} - @touchstart=${() => this.down()} - @mouseup=${() => this.up()} - @mouseleave=${() => this.leave()} - @touchend=${() => this.leave()} - @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} - @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} - /> + ${pinsFemalePattern} - - - - - - - - - - - + + + + + - - + - - - - - - + - - + + + + + + + this.down()} + @touchstart=${() => this.down()} + @mouseup=${() => this.up()} + @mouseleave=${() => this.leave()} + @touchend=${() => this.leave()} + @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} + @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} /> - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - ${ledPower && - svg``} - + + - - PWR - + + + + - - - ${led13 && - svg``} - + + + + ${ledPower && + svg``} + - - - ${ledTX && - svg``} - + + PWR + - - - ${ledRX && - svg``} - + + + ${led13 && + svg``} + - - L - TX - RX -   - + + + ${ledTX && + svg``} + - - - - PWM - + + + ${ledRX && + svg``} + - - - COMMUNICATION - + + L + TX + RX +   + - - AREF - GND - 13 - 12 - 11 - 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - TX→ 1 - RX← 0 - TX3 14 - RX3 15 - TX2 16 - RX2 17 - TX1 18 - RX1 19 - SDA 20 - SCL 21 -   - + + + + PWM + + + + + COMMUNICATION + + + + AREF + GND + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + TX→ 1 + RX← 0 + TX3 14 + RX3 15 + TX2 16 + RX2 17 + TX1 18 + RX1 19 + SDA 20 + SCL 21 +   + - - - - POWER - ANALOG IN - - - IOREF - RESET - 3.3V - 5V - GND - GND - Vin - A0 - A1 - A2 - A3 - A4 - A5 - A6 - A7 - A8 - A9 - A10 - A11 - A12 - A13 - A14 - A15 -   - + + + + POWER + ANALOG IN + + + IOREF + RESET + 3.3V + 5V + GND + GND + Vin + A0 + A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 +   + - - - Arduino MEGA - - + + + Arduino MEGA + + + `; } private down() { diff --git a/src/arduino-nano-element.stories.ts b/src/arduino-nano-element.stories.ts index cc4595a..5dfad87 100644 --- a/src/arduino-nano-element.stories.ts +++ b/src/arduino-nano-element.stories.ts @@ -5,18 +5,18 @@ import { action } from '@storybook/addon-actions'; import './arduino-nano-element'; storiesOf('Arduino Nano', module) - .addParameters({ component: 'wokwi-arduino-nano' }) + .addParameters({ component: 'ArduinoNanoElement' }) .addDecorator(withKnobs) .add( 'Nano', () => html` - + > ` ); diff --git a/src/arduino-nano-element.ts b/src/arduino-nano-element.ts index 7b9d81e..1a3becf 100644 --- a/src/arduino-nano-element.ts +++ b/src/arduino-nano-element.ts @@ -3,7 +3,8 @@ import { customElement, property, query } from 'lit/decorators.js'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; -@customElement('wokwi-arduino-nano') +import './show-pins-element'; +@customElement('ArduinoNanoElement') export class ArduinoNanoElement extends LitElement { @property() led13 = false; @property() ledRX = false; @@ -89,211 +90,228 @@ export class ArduinoNanoElement extends LitElement { render() { const { ledPower, led13, ledRX, ledTX } = this; return html` - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - D12 - D11 - D10 - D9 - D8 - D7 - D6 - D5 - D4 - D3 - D2 - GND - RST - - RX0 - - TX1 + + + + + + + - - D13 - 3V3 - AREF - A0 - A1 - A2 - A3 - A4 - A5 - A6 - A7 - 5V - RST - GND - VIN + + + + + + + + + + + D12 + D11 + D10 + D9 + D8 + D7 + D6 + D5 + D4 + D3 + D2 + GND + RST + + RX0 + + TX1 + + + D13 + 3V3 + AREF + A0 + A1 + A2 + A3 + A4 + A5 + A6 + A7 + 5V + RST + GND + VIN + + + RESET + TX + + RX + + ON + L + - - RESET - TX - - RX - - ON - L + + + + + + + + + - - - - - - + + + + + + + + - - - - - - - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + ${ledTX && + svg``} - - - - - - + + + ${ledRX && + svg``} + + + + ${ledPower && + svg``} + + + + ${led13 && + svg``} - - - - - - ${ledTX && - svg``} - - - - ${ledRX && - svg``} - - - - ${ledPower && - svg``} - - - - ${led13 && - svg``} - - - - - - this.down()} - @touchstart=${() => this.down()} - @mouseup=${() => this.up()} - @mouseleave=${() => this.leave()} - @touchend=${() => this.leave()} - @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} - @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} - /> - - + + + + + this.down()} + @touchstart=${() => this.down()} + @mouseup=${() => this.up()} + @mouseleave=${() => this.leave()} + @touchend=${() => this.leave()} + @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} + @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} + /> + + + `; } diff --git a/src/arduino-uno-element.stories.ts b/src/arduino-uno-element.stories.ts index 675a2ae..70145c9 100644 --- a/src/arduino-uno-element.stories.ts +++ b/src/arduino-uno-element.stories.ts @@ -5,7 +5,7 @@ import { html } from 'lit'; import './arduino-uno-element'; storiesOf('Arduino Uno', module) - .addParameters({ component: 'wokwi-arduino-uno' }) + .addParameters({ component: 'ArduinoUnoElement' }) .addDecorator(withKnobs) .add( 'Uno R3', diff --git a/src/arduino-uno-element.ts b/src/arduino-uno-element.ts index 63de44d..75037d5 100644 --- a/src/arduino-uno-element.ts +++ b/src/arduino-uno-element.ts @@ -4,7 +4,8 @@ import { pinsFemalePattern } from './patterns/pins-female'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; -@customElement('wokwi-arduino-uno') +import './show-pins-element'; +@customElement('ArduinoUnoElement') export class ArduinoUnoElement extends LitElement { @property() led13 = false; @property() ledRX = false; @@ -66,288 +67,294 @@ export class ArduinoUnoElement extends LitElement { render() { const { ledPower, led13, ledRX, ledTX } = this; return html` - - - - - - - + + + + + + + + + + + + - - - + ${pinsFemalePattern} - ${pinsFemalePattern} + + + + + - - - - - + + + - + - - - - - - - - - - - - - - this.down()} - @touchstart=${() => this.down()} - @mouseup=${() => this.up()} - @mouseleave=${() => this.leave()} - @touchend=${() => this.leave()} - @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} - @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} - /> + + + + + + + + + + this.down()} + @touchstart=${() => this.down()} + @mouseup=${() => this.up()} + @mouseleave=${() => this.leave()} + @touchend=${() => this.leave()} + @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} + @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} + /> - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + - - - + + + - - - - ${ledPower && - svg``} - + + + + ${ledPower && + svg``} + - - ON - + + ON + - - - ${led13 && - svg``} - + + + ${led13 && + svg``} + - - - ${ledTX && - svg``} - + + + ${ledTX && + svg``} + - - - ${ledRX && - svg``} - + + + ${ledRX && + svg``} + - - L - TX - RX -   - + + L + TX + RX +   + - - - - DIGITAL (PWM ~) - - - AREF - GND - 13 - 12 - ~11 - ~10 - ~9 - 8 - 7 - ~6 - ~5 - 4 - ~3 - 2 - TX→1 - RX←0 -   - + + + + DIGITAL (PWM ~) + + + AREF + GND + 13 + 12 + ~11 + ~10 + ~9 + 8 + 7 + ~6 + ~5 + 4 + ~3 + 2 + TX→1 + RX←0 +   + - - - - POWER - ANALOG IN - - - IOREF - RESET - 3.3V - 5V - GND - GND - Vin - A0 - A1 - A2 - A3 - A4 - A5 -   - + + + + POWER + ANALOG IN + + + IOREF + RESET + 3.3V + 5V + GND + GND + Vin + A0 + A1 + A2 + A3 + A4 + A5 +   + - - - - - ARDUINO - + + + + + ARDUINO + - + - UNO - + UNO + + `; } private down() { diff --git a/src/breadboard-element.stories.ts b/src/breadboard-element.stories.ts index 8dca0d7..caca0ad 100644 --- a/src/breadboard-element.stories.ts +++ b/src/breadboard-element.stories.ts @@ -3,7 +3,7 @@ import './breadboard-element'; export default { title: 'Breadboard', - component: 'wokwi-breadboard', + component: 'BreaboardElement', argTypes: { type: { control: { @@ -19,7 +19,7 @@ export default { const Template = ({ type }) => html` - + `; diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index f437a82..378642b 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -1,7 +1,9 @@ -import { html, LitElement, svg } from 'lit'; +import { html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin } from './pin'; -@customElement('wokwi-breadboard') + +import './show-pins-element'; +@customElement('BreadboardElement') export class BreadboardElement extends LitElement { @property() type: 'small' | 'normal' = 'small'; @@ -67,988 +69,990 @@ export class BreadboardElement extends LitElement { // svg is coming from assets folder return type === 'normal' ? html` - - - + + + + + + + + + - - - - - - - - - - -
+ + + + +
+
+
+ a +
+
+
-
+ a + + + + + + +
- a +
+ b +
-
-
- - a - -
-
- - - -
-
+ b + + + + + + +
- b +
+ c +
-
-
- - b - - - - - - -
-
+ c + + + + + + +
- c +
+ d +
-
-
- - c - - - - - - -
-
+ d + + + + + + +
- d +
+ e +
-
-
- - d - - - - - - -
-
+ e + + + + + + +
- e +
+ f +
-
-
- - e - - - - - - -
-
-
- f -
-
-
- - f - -
-
- - - -
-
+ + + + + +
- h +
+ h +
-
-
- - h - - - - - - -
-
-
- g -
-
-
- - g - -
-
- - - -
-
+ + + + + +
- 0 +
+ g +
-
-
- - 0 - - - - - - -
-
+ g + + + + + + +
- 1 +
+ 0 +
-
-
- - 1 - - - - - - -
-
+ 0 + + + + + + +
- 2 +
+ 1 +
-
-
- - 2 - - - - - - -
-
+ 1 + + + + + + +
- 3 +
+ 2 +
-
-
- - 3 - - - - - - - -
-
+ 2 + + + + + + +
- 4 +
+ 3 +
-
-
- - 4 - - - - - - -
+ + 3 + + + + + + + +
+
+
+ 4 +
+
+
-
+ 4 + + + + + + +
- 5 +
+ 5 +
-
-
- - 5 - -
-
- - - -
-
+ 5 + + + + + + +
- 6 +
+ 6 +
-
-
- - 6 - - - - - - -
-
+ 6 + + + + + + +
- 7 +
+ 7 +
-
-
- - 7 - - - - - - -
-
+ 7 + + + + + + +
- 8 +
+ 8 +
-
-
- - 8 - - - - - - -
-
+ 8 + + + + + + +
- 9 +
+ 9 +
-
-
- - 9 - - - - - - -
-
+ 9 + + + + + + +
- 10 +
+ 10 +
-
-
- - 10 - - - - - - -
-
+ 10 + + + + + + +
- 11 +
+ 11 +
-
-
- - 11 - - +
+ + 11 + +
+
- - - - - - Text is not SVG - cannot display - - - - + + + + + Text is not SVG - cannot display + + + + + ` : html` + `; } } diff --git a/src/react-types.ts b/src/react-types.ts index 1760b95..360854a 100644 --- a/src/react-types.ts +++ b/src/react-types.ts @@ -50,9 +50,9 @@ import { StepperMotorElement } from './stepper-motor-element'; import { HX711Element } from './hx711-element'; import { KS2EMDC5Element } from './ks2e-m-dc5-element'; import { BiaxialStepperElement } from './biaxial-stepper-element'; -import type React from 'react'; import { BreadboardElement } from './breadboard-element'; -import { ShowPinsElement } from './show-pins-element'; + +import type React from 'react'; type WokwiElement = Partial & React.ClassAttributes; @@ -109,7 +109,6 @@ declare global { KS2EMDC5: WokwiElement; BiaxialStepper: WokwiElement; Breadboard: WokwiElement; - ShowPins: WokwiElement; } } } diff --git a/src/rgb-led-element.ts b/src/rgb-led-element.ts index e98dab2..e074682 100644 --- a/src/rgb-led-element.ts +++ b/src/rgb-led-element.ts @@ -2,7 +2,7 @@ import { html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin } from '.'; -@customElement('wokwi-rgb-led') +@customElement('RgbLed') export class RGBLedElement extends LitElement { @property() ledRed = 0; @property() ledGreen = 0; From 8fec237c3303518f63d4d5afa7a5e76d0b43ed32 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Fri, 29 Mar 2024 20:20:53 +0200 Subject: [PATCH 17/27] fix package.json conflict This reverts commit 4b5c86f5a41ad8330a95346045689953570ef6ab. --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 6a63398..78bc6ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,10 @@ { "name": "@b.borisov/cu-elements", +<<<<<<< HEAD "version": "1.4.17", +======= + "version": "1.4.15", +>>>>>>> parent of 4b5c86f (update version) "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From e1d853d5e638d96bc8a6349201cd3840fc4cfbed Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Fri, 29 Mar 2024 20:24:15 +0200 Subject: [PATCH 18/27] Revert "update version" This reverts commit 4b5c86f5a41ad8330a95346045689953570ef6ab. --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index 78bc6ec..6a63398 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,6 @@ { "name": "@b.borisov/cu-elements", -<<<<<<< HEAD "version": "1.4.17", -======= - "version": "1.4.15", ->>>>>>> parent of 4b5c86f (update version) "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From e9e3ac948f670dc59f9b5b9bb964a94431d1d834 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Fri, 29 Mar 2024 20:25:35 +0200 Subject: [PATCH 19/27] Revert "update version" This reverts commit 4b5c86f5a41ad8330a95346045689953570ef6ab. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a63398..2b7d171 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.17", + "version": "1.4.16", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From 7e2566088c3c5cddc3bcdbb3d67250dd95cf9905 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 2 Apr 2024 20:57:55 +0300 Subject: [PATCH 20/27] add separate main and mcu breaboards --- src/arduino-mega-element.ts | 1 + src/breadboard-element.ts | 3 +- src/index.ts | 2 + src/main-breadboard-element.stories.ts | 13 + src/main-breadboard-element.ts | 1013 ++++++++++++++++++++++++ src/mcu-breadboard-element.stories.ts | 13 + src/mcu-breadboard-element.ts | 650 +++++++++++++++ src/react-types.ts | 4 + src/show-pins-element.stories.ts | 2 +- src/show-pins-element.ts | 49 +- 10 files changed, 1744 insertions(+), 6 deletions(-) create mode 100644 src/main-breadboard-element.stories.ts create mode 100644 src/main-breadboard-element.ts create mode 100644 src/mcu-breadboard-element.stories.ts create mode 100644 src/mcu-breadboard-element.ts diff --git a/src/arduino-mega-element.ts b/src/arduino-mega-element.ts index b7cd36e..4037794 100644 --- a/src/arduino-mega-element.ts +++ b/src/arduino-mega-element.ts @@ -3,6 +3,7 @@ import { customElement, property, query } from 'lit/decorators.js'; import { pinsFemalePattern } from './patterns/pins-female'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; + @customElement('wokwi-arduino-mega') export class ArduinoMegaElement extends LitElement { @property() led13 = false; diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index f437a82..216f4b0 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -1,6 +1,7 @@ import { html, LitElement, svg } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin } from './pin'; + @customElement('wokwi-breadboard') export class BreadboardElement extends LitElement { @property() type: 'small' | 'normal' = 'small'; @@ -63,7 +64,7 @@ export class BreadboardElement extends LitElement { } render() { - const { type, pinInfo } = this; + const { type } = this; // svg is coming from assets folder return type === 'normal' ? html` diff --git a/src/index.ts b/src/index.ts index b00d139..fbbbd15 100644 --- a/src/index.ts +++ b/src/index.ts @@ -53,3 +53,5 @@ export { KS2EMDC5Element } from './ks2e-m-dc5-element'; export { BiaxialStepperElement } from './biaxial-stepper-element'; export { BreadboardElement } from './breadboard-element'; export { ShowPinsElement } from './show-pins-element'; +export { MainBreadboardElement } from './main-breadboard-element'; +export { McuBreadboardElement } from './mcu-breadboard-element'; diff --git a/src/main-breadboard-element.stories.ts b/src/main-breadboard-element.stories.ts new file mode 100644 index 0000000..1a78362 --- /dev/null +++ b/src/main-breadboard-element.stories.ts @@ -0,0 +1,13 @@ +import { html } from 'lit'; +import './main-breadboard-element'; + +export default { + title: 'Main Breadboard', + component: 'wokwi-main-breadboard', + argTypes: {}, + args: {}, +}; + +const Template = () => html``; + +export const Default = Template.bind({}); diff --git a/src/main-breadboard-element.ts b/src/main-breadboard-element.ts new file mode 100644 index 0000000..704d581 --- /dev/null +++ b/src/main-breadboard-element.ts @@ -0,0 +1,1013 @@ +import { html, LitElement, svg } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { ElementPin } from './pin'; + +@customElement('wokwi-main-breadboard') +export class MainBreadboardElement extends LitElement { + pinInfo: ElementPin[] = []; + + constructNormalPins() { + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 12; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(65 + col)}${row}`, + x: 10.3 + col * 17.15, + y: 26 + row * 17.15, + } as ElementPin); + } + } + + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 12; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(69 + col)}${row}`, + x: 113 + col * 17.15, + y: 26 + row * 17.15, + } as ElementPin); + } + } + } + + firstUpdated() { + this.constructNormalPins(); + } + + render() { + return html` + + + + + + + + + + + + + + +
+
+
+ a +
+
+
+ + a + +
+
+ + + +
+
+
+ b +
+
+
+ + b + +
+
+ + + +
+
+
+ c +
+
+
+ + c + +
+
+ + + +
+
+
+ d +
+
+
+ + d + +
+
+ + + +
+
+
+ e +
+
+
+ + e + +
+
+ + + +
+
+
+ f +
+
+
+ + f + +
+
+ + + +
+
+
+ h +
+
+
+ + h + +
+
+ + + +
+
+
+ g +
+
+
+ + g + +
+
+ + + +
+
+
+ 0 +
+
+
+ + 0 + +
+
+ + + +
+
+
+ 1 +
+
+
+ + 1 + +
+
+ + + +
+
+
+ 2 +
+
+
+ + 2 + +
+
+ + + +
+
+
+ 3 +
+
+
+ + 3 + +
+
+ + + + +
+
+
+ 4 +
+
+
+ + 4 + +
+
+ + + +
+
+
+ 5 +
+
+
+ + 5 + +
+
+ + + +
+
+
+ 6 +
+
+
+ + 6 + +
+
+ + + +
+
+
+ 7 +
+
+
+ + 7 + +
+
+ + + +
+
+
+ 8 +
+
+
+ + 8 + +
+
+ + + +
+
+
+ 9 +
+
+
+ + 9 + +
+
+ + + +
+
+
+ 10 +
+
+
+ + 10 + +
+
+ + + +
+
+
+ 11 +
+
+
+ + 11 + +
+
+
+ + + + + Text is not SVG - cannot display + + + +
+ `; + } +} diff --git a/src/mcu-breadboard-element.stories.ts b/src/mcu-breadboard-element.stories.ts new file mode 100644 index 0000000..3543664 --- /dev/null +++ b/src/mcu-breadboard-element.stories.ts @@ -0,0 +1,13 @@ +import { html } from 'lit'; +import './mcu-breadboard-element'; + +export default { + title: 'Mcu Breadboard', + component: 'wokwi-mcu-breadboard', + argTypes: {}, + args: {}, +}; + +const Template = () => html``; + +export const Default = Template.bind({}); diff --git a/src/mcu-breadboard-element.ts b/src/mcu-breadboard-element.ts new file mode 100644 index 0000000..5d6ab88 --- /dev/null +++ b/src/mcu-breadboard-element.ts @@ -0,0 +1,650 @@ +import { html, LitElement, svg } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { ElementPin } from './pin'; + +@customElement('wokwi-mcu-breadboard') +export class McuBreadboardElement extends LitElement { + pinInfo: ElementPin[] = []; + + constructSmallPins() { + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 4; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(65 + col)}${row}`, + x: 10.3 + col * 17, + y: 26 + row * 17, + } as ElementPin); + } + } + + for (let col = 0; col < 4; col++) { + for (let row = 0; row < 4; row++) { + this.pinInfo.push({ + name: `${String.fromCharCode(69 + col)}${row}`, + x: 112.7 + col * 17, + y: 26 + row * 17, + } as ElementPin); + } + } + } + + firstUpdated() { + this.constructSmallPins(); + } + + render() { + return html` + + + + + + + + + + + + + + +
+
+
+ a +
+
+
+ + a + +
+
+ + + +
+
+
+ b +
+
+
+ + b + +
+
+ + + +
+
+
+ c +
+
+
+ + c + +
+
+ + + +
+
+
+ d +
+
+
+ + d + +
+
+ + + +
+
+
+ e +
+
+
+ + e + +
+
+ + + +
+
+
+ f +
+
+
+ + f + +
+
+ + + +
+
+
+ h +
+
+
+ + h + +
+
+ + + +
+
+
+ g +
+
+
+ + g + +
+
+ + + +
+
+
+ 0 +
+
+
+ + 0 + +
+
+ + + +
+
+
+ 1 +
+
+
+ + 1 + +
+
+ + + +
+
+
+ 2 +
+
+
+ + 2 + +
+
+ + + +
+
+
+ 3 +
+
+
+ + 3 + +
+
+ +
+ + + + + Text is not SVG - cannot display + + + +
+ `; + } +} diff --git a/src/react-types.ts b/src/react-types.ts index 1760b95..97d43f2 100644 --- a/src/react-types.ts +++ b/src/react-types.ts @@ -53,6 +53,8 @@ import { BiaxialStepperElement } from './biaxial-stepper-element'; import type React from 'react'; import { BreadboardElement } from './breadboard-element'; import { ShowPinsElement } from './show-pins-element'; +import { MainBreadboardElement } from './main-breadboard-element'; +import { McuBreadboardElement } from './mcu-breadboard-element'; type WokwiElement = Partial & React.ClassAttributes; @@ -110,6 +112,8 @@ declare global { BiaxialStepper: WokwiElement; Breadboard: WokwiElement; ShowPins: WokwiElement; + MainBreadboard: WokwiElement; + MCUBreadboard: WokwiElement; } } } diff --git a/src/show-pins-element.stories.ts b/src/show-pins-element.stories.ts index 85ba93b..cf25904 100644 --- a/src/show-pins-element.stories.ts +++ b/src/show-pins-element.stories.ts @@ -27,7 +27,7 @@ const Template = ({ pinColor, pinType, pinWidth, pinHeight, pinRadius }) => html pinHeight=${pinHeight} pinRadius=${pinRadius} > - + `; export const Default = Template.bind({}); diff --git a/src/show-pins-element.ts b/src/show-pins-element.ts index 808b6fb..e36e4dd 100644 --- a/src/show-pins-element.ts +++ b/src/show-pins-element.ts @@ -77,13 +77,38 @@ export class ShowPinsElement extends LitElement { document.dispatchEvent(new CustomEvent('pin-mouseout', { detail: { pin, index: idx } })); this.requestUpdate(); } - handlePinClick({ pin, idx }: { pin: ElementPin; idx: number }) { + handlePinClick({ + pin, + idx, + }: { + pin: { + elementName: string; + pinName: string; + x: number; + y: number; + }; + idx: number; + }) { console.log('pin clicked', pin, idx); - document.dispatchEvent(new CustomEvent('pin-click', { detail: { pin, index: idx } })); + document.dispatchEvent( + new CustomEvent('pin-click', { + detail: { + // if clicked on main breadboard, this will be the pin name --> MAINA11 + pin: { + pinName: pin.elementName, + elementName: pin.pinName, + x: pin.x, + y: pin.y, + }, + index: idx, + }, + }) + ); } render() { const pinInfo = this.slotChild?.pinInfo ?? []; + const elementName = this.slotChild?.localName; const { pinColor, pinType, pinWidth, pinHeight, pinRadius } = this; return html`
this.handleSlotChange()}> @@ -100,7 +125,15 @@ export class ShowPinsElement extends LitElement { style="transition: fill 0.3s;" @mouseover=${this.handleMouseOver.bind(this, { pin, idx })} @mouseout=${this.handleMouseOut.bind(this, { pin, idx })} - @click=${this.handlePinClick.bind(this, { pin, idx })} + @click=${this.handlePinClick.bind(this, { + pin: { + elementName: elementName ?? '', + pinName: pin.name, + x: pin.x, + y: pin.y, + }, + idx, + })} >${pin.name} ` : svg` @@ -113,7 +146,15 @@ export class ShowPinsElement extends LitElement { style="transition: fill 0.3s;" @mouseover=${this.handleMouseOver.bind(this, { pin, idx })} @mouseout=${this.handleMouseOut.bind(this, { pin, idx })} - @click=${this.handlePinClick.bind(this, { pin, idx })} + @click=${this.handlePinClick.bind(this, { + pin: { + elementName: elementName || '', + pinName: pin.name, + x: pin.x, + y: pin.y, + }, + idx, + })} >${pin.name} ` )} From f30e94ddb9c55bfe8b6e428244900a80f25ddaac Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 2 Apr 2024 21:00:10 +0300 Subject: [PATCH 21/27] update package js --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b7d171..cebcdc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.16", + "version": "1.4.18", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From aa2b35beec8cfadc288d0601272c88b6d30f5b17 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 2 Apr 2024 21:02:27 +0300 Subject: [PATCH 22/27] add show pins element as react type --- src/breadboard-element.ts | 1763 ++++++++++++++++++------------------- src/react-types.ts | 5 +- 2 files changed, 884 insertions(+), 884 deletions(-) diff --git a/src/breadboard-element.ts b/src/breadboard-element.ts index c3b17e8..9e4e162 100644 --- a/src/breadboard-element.ts +++ b/src/breadboard-element.ts @@ -65,993 +65,992 @@ export class BreadboardElement extends LitElement { render() { const { type } = this; + // svg is coming from assets folder return type === 'normal' ? html` - - - - - - - - - - - - + + + - - -
+ + + + + + + + + +
+
-
- a -
+ a
-
- +
+ + a + +
+
+ + + +
- a - - - - - - -
-
- b -
+ b
-
- +
+ + b + +
+
+ + + +
- b - - - - - - -
-
- c -
+ c
-
- +
+ + c + +
+
+ + + +
- c - - - - - - -
-
- d -
+ d
-
- +
+ + d + +
+
+ + + +
- d - - - - - - -
-
- e -
+ e
-
- +
+ + e + +
+
+ + + +
- e - - - - - - -
-
- f -
+ f
-
- +
+ + f + +
+
+ + + +
- f - - - - - - -
-
- h -
+ h
-
- +
+ + h + +
+
+ + + +
- h - - - - - - -
-
- g -
+ g
-
- +
+ + g + +
+
+ + + +
- g - - - - - - -
-
- 0 -
+ 0
-
- +
+ + 0 + +
+
+ + + +
- 0 - - - - - - -
-
- 1 -
+ 1
-
- +
+ + 1 + +
+
+ + + +
- 1 - - - - - - -
-
- 2 -
+ 2
-
- +
+ + 2 + +
+
+ + + +
- 2 - - - - - - -
-
- 3 -
+ 3
-
- +
+ + 3 + +
+
+ + + + +
- 3 - - - - - - - -
-
- 4 -
+ 4
-
- +
+ + 4 + +
+
+ + + +
- 4 - - - - - - -
-
- 5 -
+ 5
-
- +
+ + 5 + +
+
+ + + +
- 5 - - - - - - -
-
- 6 -
+ 6
-
- +
+ + 6 + +
+
+ + + +
- 6 - - - - - - -
-
- 7 -
+ 7
-
- +
+ + 7 + +
+
+ + + +
- 7 - - - - - - -
-
- 8 -
+ 8
-
- +
+ + 8 + +
+
+ + + +
- 8 - - - - - - -
-
- 9 -
+ 9
-
- +
+ + 9 + +
+
+ + + +
- 9 - - - - - - -
-
- 10 -
+ 10
-
- +
+ + 10 + +
+
+ + + +
- 10 - - - - - - -
-
- 11 -
+ 11
-
- - 11 - -
-
- - - - - - Text is not SVG - cannot display +
+
+ + 11 - -
-
-
+ + + + + + + + Text is not SVG - cannot display + + + + ` : html` = Partial & React.ClassAttributes; declare global { From 6bdac7d3fad341d40441ed39cff943d95f06a21e Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 2 Apr 2024 21:11:18 +0300 Subject: [PATCH 23/27] update arduino nano and uno story names --- package.json | 2 +- src/arduino-nano-element.stories.ts | 4 +- src/arduino-nano-element.ts | 400 ++++++++++----------- src/arduino-uno-element.ts | 521 ++++++++++++++-------------- 4 files changed, 451 insertions(+), 476 deletions(-) diff --git a/package.json b/package.json index cebcdc2..5e3cb42 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.18", + "version": "1.4.19", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", diff --git a/src/arduino-nano-element.stories.ts b/src/arduino-nano-element.stories.ts index 5dfad87..6bac051 100644 --- a/src/arduino-nano-element.stories.ts +++ b/src/arduino-nano-element.stories.ts @@ -10,13 +10,13 @@ storiesOf('Arduino Nano', module) .add( 'Nano', () => html` - + > ` ); diff --git a/src/arduino-nano-element.ts b/src/arduino-nano-element.ts index 1a3becf..7b9d81e 100644 --- a/src/arduino-nano-element.ts +++ b/src/arduino-nano-element.ts @@ -3,8 +3,7 @@ import { customElement, property, query } from 'lit/decorators.js'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; -import './show-pins-element'; -@customElement('ArduinoNanoElement') +@customElement('wokwi-arduino-nano') export class ArduinoNanoElement extends LitElement { @property() led13 = false; @property() ledRX = false; @@ -90,228 +89,211 @@ export class ArduinoNanoElement extends LitElement { render() { const { ledPower, led13, ledRX, ledTX } = this; return html` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - D12 - D11 - D10 - D9 - D8 - D7 - D6 - D5 - D4 - D3 - D2 - GND - RST - - RX0 - - TX1 - - - D13 - 3V3 - AREF - A0 - A1 - A2 - A3 - A4 - A5 - A6 - A7 - 5V - RST - GND - VIN + + + + + + + + + + + + + + + - - RESET - TX - - RX - - ON - L + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + - - - - - - - + + D12 + D11 + D10 + D9 + D8 + D7 + D6 + D5 + D4 + D3 + D2 + GND + RST + + RX0 + + TX1 + + + D13 + 3V3 + AREF + A0 + A1 + A2 + A3 + A4 + A5 + A6 + A7 + 5V + RST + GND + VIN + + + RESET + TX + + RX + + ON + L + - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - ${ledTX && - svg``} + + + + + - - - ${ledRX && - svg``} + + + + + + + + - - - ${ledPower && - svg``} + + + + + + + + + + + + + - - - ${led13 && - svg``} + + + + + + + - - - - - this.down()} - @touchstart=${() => this.down()} - @mouseup=${() => this.up()} - @mouseleave=${() => this.leave()} - @touchend=${() => this.leave()} - @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} - @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} - /> - - - + + + + ${ledTX && + svg``} + + + + ${ledRX && + svg``} + + + + ${ledPower && + svg``} + + + + ${led13 && + svg``} + + + + + + + this.down()} + @touchstart=${() => this.down()} + @mouseup=${() => this.up()} + @mouseleave=${() => this.leave()} + @touchend=${() => this.leave()} + @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} + @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} + /> + + `; } diff --git a/src/arduino-uno-element.ts b/src/arduino-uno-element.ts index 75037d5..63de44d 100644 --- a/src/arduino-uno-element.ts +++ b/src/arduino-uno-element.ts @@ -4,8 +4,7 @@ import { pinsFemalePattern } from './patterns/pins-female'; import { analog, ElementPin, i2c, spi, usart } from './pin'; import { SPACE_KEYS } from './utils/keys'; -import './show-pins-element'; -@customElement('ArduinoUnoElement') +@customElement('wokwi-arduino-uno') export class ArduinoUnoElement extends LitElement { @property() led13 = false; @property() ledRX = false; @@ -67,294 +66,288 @@ export class ArduinoUnoElement extends LitElement { render() { const { ledPower, led13, ledRX, ledTX } = this; return html` - - - - - - - - - - - - + + + + + + + - ${pinsFemalePattern} + + + - - - - - + ${pinsFemalePattern} - - - + + + + + - + + - - - - - - - - - - this.down()} - @touchstart=${() => this.down()} - @mouseup=${() => this.up()} - @mouseleave=${() => this.leave()} - @touchend=${() => this.leave()} - @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} - @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} - /> + + - - - - - - - - - - - + + + + + + + + + + this.down()} + @touchstart=${() => this.down()} + @mouseup=${() => this.up()} + @mouseleave=${() => this.leave()} + @touchend=${() => this.leave()} + @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()} + @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()} + /> - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + + + + + + + + + + - - - + + + + - - - - ${ledPower && - svg``} - + + + - - ON - + + + + ${ledPower && + svg``} + - - - ${led13 && - svg``} - + + ON + - - - ${ledTX && - svg``} - + + + ${led13 && + svg``} + - - - ${ledRX && - svg``} - + + + ${ledTX && + svg``} + - - L - TX - RX -   - + + + ${ledRX && + svg``} + - - - - DIGITAL (PWM ~) - - - AREF - GND - 13 - 12 - ~11 - ~10 - ~9 - 8 - 7 - ~6 - ~5 - 4 - ~3 - 2 - TX→1 - RX←0 -   - + + L + TX + RX +   + - - - - POWER - ANALOG IN - - - IOREF - RESET - 3.3V - 5V - GND - GND - Vin - A0 - A1 - A2 - A3 - A4 - A5 -   - + + + + DIGITAL (PWM ~) + + + AREF + GND + 13 + 12 + ~11 + ~10 + ~9 + 8 + 7 + ~6 + ~5 + 4 + ~3 + 2 + TX→1 + RX←0 +   + - - - - - ARDUINO - + + + + POWER + ANALOG IN + + + IOREF + RESET + 3.3V + 5V + GND + GND + Vin + A0 + A1 + A2 + A3 + A4 + A5 +   + - + + + + + ARDUINO + + + - UNO - - + UNO + `; } private down() { From 37424c5028cc3ea9fae2897efc8d5240fcbe7f43 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 2 Apr 2024 21:13:21 +0300 Subject: [PATCH 24/27] rename rgb led story --- package.json | 2 +- src/rgb-led-element.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5e3cb42..b0919c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.19", + "version": "1.4.20", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", diff --git a/src/rgb-led-element.ts b/src/rgb-led-element.ts index e074682..e98dab2 100644 --- a/src/rgb-led-element.ts +++ b/src/rgb-led-element.ts @@ -2,7 +2,7 @@ import { html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin } from '.'; -@customElement('RgbLed') +@customElement('wokwi-rgb-led') export class RGBLedElement extends LitElement { @property() ledRed = 0; @property() ledGreen = 0; From bfed8363c5256214219e3de8a9b8bf3185e23ea5 Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Mon, 15 Apr 2024 18:46:10 +0300 Subject: [PATCH 25/27] add no drag class to prevent dragging --- src/show-pins-element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/show-pins-element.ts b/src/show-pins-element.ts index e36e4dd..7067cd1 100644 --- a/src/show-pins-element.ts +++ b/src/show-pins-element.ts @@ -110,7 +110,7 @@ export class ShowPinsElement extends LitElement { const pinInfo = this.slotChild?.pinInfo ?? []; const elementName = this.slotChild?.localName; const { pinColor, pinType, pinWidth, pinHeight, pinRadius } = this; - return html`
+ return html`
this.handleSlotChange()}> ${pinInfo.map((pin, idx) => From abe788878107752e42ec93ce95d75d2a16843dfa Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Mon, 15 Apr 2024 18:47:01 +0300 Subject: [PATCH 26/27] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b0919c0..6fd3035 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.20", + "version": "1.4.21", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", From 775b1c520f916ddcb5c5ec5dcc8caf08b41c840f Mon Sep 17 00:00:00 2001 From: bobikenobi12 Date: Tue, 16 Apr 2024 16:13:54 +0300 Subject: [PATCH 27/27] add attiny85 --- package.json | 2 +- src/attiny85-element.stories.ts | 21 + src/attiny85-element.ts | 4070 ++++++++++++++++++++++++++++++ src/index.ts | 1 + src/react-types.ts | 2 + src/show-pins-element.stories.ts | 7 +- 6 files changed, 4098 insertions(+), 5 deletions(-) create mode 100644 src/attiny85-element.stories.ts create mode 100644 src/attiny85-element.ts diff --git a/package.json b/package.json index 6fd3035..811014b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@b.borisov/cu-elements", - "version": "1.4.21", + "version": "1.4.22", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", diff --git a/src/attiny85-element.stories.ts b/src/attiny85-element.stories.ts new file mode 100644 index 0000000..9dd2a6a --- /dev/null +++ b/src/attiny85-element.stories.ts @@ -0,0 +1,21 @@ +import { html } from 'lit'; +import './attiny85-element'; + +export default { + title: 'Attiny85', + component: 'wokwi-attiny85', + argTypes: { + value: { control: { type: 'number', min: 1, max: 10, step: 1 } }, + }, + args: { + value: 5, + }, +}; + +const Template = ({ value }) => html``; + +export const Default = Template.bind({}); +Default.args = { value: 5 }; + +export const Large = Template.bind({}); +Large.args = { value: 10 }; diff --git a/src/attiny85-element.ts b/src/attiny85-element.ts new file mode 100644 index 0000000..c73f81a --- /dev/null +++ b/src/attiny85-element.ts @@ -0,0 +1,4070 @@ +import { html, LitElement, svg } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { ElementPin } from './pin'; + +@customElement('wokwi-attiny85') +export class Attiny85Element extends LitElement { + pinInfo: ElementPin[] = []; + + constructPins() { + for (let i = 1; i < 4; i++) { + this.pinInfo.push({ + name: `PB${i}`, + x: 20 + i * 19.4, + y: 10, + } as ElementPin); + } + + for (let i = 0; i < 4; i++) { + this.pinInfo.push({ + name: `PB${i}`, + x: 10 + i * 10, + y: 200, + } as ElementPin); + } + } + + firstUpdated() { + this.constructPins(); + } + + render() { + return html` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `; + } +} diff --git a/src/index.ts b/src/index.ts index fbbbd15..347f97b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,3 +55,4 @@ export { BreadboardElement } from './breadboard-element'; export { ShowPinsElement } from './show-pins-element'; export { MainBreadboardElement } from './main-breadboard-element'; export { McuBreadboardElement } from './mcu-breadboard-element'; +export { Attiny85Element } from './attiny85-element'; diff --git a/src/react-types.ts b/src/react-types.ts index 67aac48..5180b38 100644 --- a/src/react-types.ts +++ b/src/react-types.ts @@ -56,6 +56,7 @@ import { MainBreadboardElement } from './main-breadboard-element'; import { McuBreadboardElement } from './mcu-breadboard-element'; import type React from 'react'; +import { Attiny85Element } from './attiny85-element'; type WokwiElement = Partial & React.ClassAttributes; @@ -115,6 +116,7 @@ declare global { ShowPins: WokwiElement; MainBreadboard: WokwiElement; MCUBreadboard: WokwiElement; + Attiny85: WokwiElement; } } } diff --git a/src/show-pins-element.stories.ts b/src/show-pins-element.stories.ts index cf25904..8625ef8 100644 --- a/src/show-pins-element.stories.ts +++ b/src/show-pins-element.stories.ts @@ -14,9 +14,9 @@ export default { args: { pinColor: 'transparent', pinType: 'circle', - pinWidth: 5, - pinHeight: 5, - pinRadius: 2.5, + pinWidth: 10, + pinHeight: 10, + pinRadius: 10, }, }; @@ -27,7 +27,6 @@ const Template = ({ pinColor, pinType, pinWidth, pinHeight, pinRadius }) => html pinHeight=${pinHeight} pinRadius=${pinRadius} > - `; export const Default = Template.bind({});